Mercurial > hg > pulseaudio
changeset 72:3003bf4192f2
src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java: the
list of formats recognized by PulseAudio is being set here, so it can
be used by all DataLines. Also made some changes to get*LineInfo() and
isLineSupported()
src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java:
changed the constructor
author | Ioana Ivan |
---|---|
date | Wed, 13 Aug 2008 14:22:35 -0400 |
parents | 9ed589465932 |
children | 20b37b004b8e |
files | ChangeLog build.xml src/java/org/classpath/icedtea/pulseaudio/EventLoop.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java src/native/org_classpath_icedtea_pulseaudio_Operation.c |
diffstat | 8 files changed, 508 insertions(+), 301 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Wed Aug 13 13:17:13 2008 -0400 +++ b/ChangeLog Wed Aug 13 14:22:35 2008 -0400 @@ -1,3 +1,13 @@ +2008-08-13 Ioana Ivan <iivan@redhat.com> + + * src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java: the + list of formats recognized by PulseAudio is being set here, so it can + be used by all DataLines. Also made some changes to get*LineInfo() and + isLineSupported() + *src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java: + changed the constructor + + 2008-08-11 Joshua Sumali <jsumali@redhat.com> * configure.ac: Add check for libpulse.
--- a/build.xml Wed Aug 13 13:17:13 2008 -0400 +++ b/build.xml Wed Aug 13 14:22:35 2008 -0400 @@ -40,6 +40,7 @@ <class name="org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine"/> <class name="org.classpath.icedtea.pulseaudio.PulseAudioClip"/> <class name="org.classpath.icedtea.pulseaudio.PulseAudioStreamVolumeControl"/> + <class name="org.classpath.icedtea.pulseaudio.Operation"/> </javah> </target>
--- a/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java Wed Aug 13 13:17:13 2008 -0400 +++ b/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java Wed Aug 13 14:22:35 2008 -0400 @@ -105,6 +105,7 @@ static { try { String library = new java.io.File(".").getCanonicalPath() + + java.io.File.separatorChar + System.mapLibraryName("pulse-java"); System.out.println(library);
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java Wed Aug 13 13:17:13 2008 -0400 +++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java Wed Aug 13 14:22:35 2008 -0400 @@ -41,7 +41,10 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.concurrent.Semaphore; import javax.sound.sampled.AudioFormat; @@ -57,17 +60,25 @@ import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.Mixer; import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.TargetDataLine; +import javax.sound.sampled.AudioFormat.Encoding; import javax.sound.sampled.Control.Type; + + public class PulseAudioMixer implements javax.sound.sampled.Mixer { // singleton public EventLoop eventLoop; public Thread eventLoopThread; + + private Line.Info[] sourceLineInfos; + private Line.Info[] targetLineInfos; private static PulseAudioMixer _instance = null; private static final String DEFAULT_APP_NAME = "Java App"; + private static final String PULSEAUDIO_FORMAT_KEY = "PulseAudioFormatKey"; private boolean isOpen = false; @@ -83,6 +94,9 @@ private PulseAudioMixer() { lineListeners = new ArrayList<LineListener>(); sourceLines = new ArrayList<PulseAudioSourceDataLine>(); + AudioFormat[] formats = getSupportedFormats(); + sourceLineInfos = new Line.Info[] {new DataLine.Info(SourceDataLine.class, formats, AudioSystem.NOT_SPECIFIED, AudioSystem.NOT_SPECIFIED)}; + targetLineInfos = new Line.Info[] {new DataLine.Info(TargetDataLine.class, formats, AudioSystem.NOT_SPECIFIED, AudioSystem.NOT_SPECIFIED)}; // _targetLines = new ArrayList<PulseAudioTargetDataLine>(); } @@ -93,6 +107,174 @@ return _instance; } +private AudioFormat[] getSupportedFormats() { + + List<AudioFormat> supportedFormats = new ArrayList<AudioFormat>(); + + Map<String, Object> properties; + + int[] channelSizes = new int[] { 1, 2, 5 }; + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_U8"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + int sampleSize = 8; // in bits + AudioFormat PA_SAMPLE_U8 = new AudioFormat(Encoding.PCM_UNSIGNED, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size in bytes + AudioSystem.NOT_SPECIFIED, // frame rate + false, // big endian? + properties); + + supportedFormats.add(PA_SAMPLE_U8); + } + + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_ALAW"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + + int sampleSize = 8; + final AudioFormat PA_SAMPLE_ALAW = new AudioFormat(Encoding.ALAW, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size + AudioSystem.NOT_SPECIFIED, // frame rate + false, // big endian? + properties); + + supportedFormats.add(PA_SAMPLE_ALAW); + } + + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_ULAW"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + + int sampleSize = 8; + final AudioFormat PA_SAMPLE_ULAW = new AudioFormat(Encoding.ULAW, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size + AudioSystem.NOT_SPECIFIED, // frame rate + false, // big endian? + properties); + + supportedFormats.add(PA_SAMPLE_ULAW); + } + + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S16BE"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + + int sampleSize = 16; + final AudioFormat PA_SAMPLE_S16BE = new AudioFormat( + Encoding.PCM_SIGNED, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size + AudioSystem.NOT_SPECIFIED, // frame rate + true, // big endian? + properties); + + supportedFormats.add(PA_SAMPLE_S16BE); + } + + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S16LE"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + + int sampleSize = 16; + final AudioFormat A_SAMPLE_S16LE = new AudioFormat( + Encoding.PCM_SIGNED, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size + AudioSystem.NOT_SPECIFIED, // frame rate + false, // big endian? + properties); + + supportedFormats.add(A_SAMPLE_S16LE); + } + + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S32BE"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + + int sampleSize = 32; + final AudioFormat PA_SAMPLE_S32BE = new AudioFormat( + Encoding.PCM_SIGNED, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size + AudioSystem.NOT_SPECIFIED, // frame rate + true, // big endian? + properties); + + supportedFormats.add(PA_SAMPLE_S32BE); + } + + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S32LE"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + + int sampleSize = 32; + final AudioFormat PA_SAMPLE_S32LE = new AudioFormat( + Encoding.PCM_SIGNED, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size + AudioSystem.NOT_SPECIFIED, // frame rate + false, // big endian? + properties); + + supportedFormats.add(PA_SAMPLE_S32LE); + } + + return supportedFormats.toArray(new AudioFormat[0]); + } + + @Override public Line getLine(javax.sound.sampled.Line.Info info) throws LineUnavailableException { @@ -100,62 +282,61 @@ if (!this.isOpen) { throw new LineUnavailableException(); } - - PulseAudioSourceDataLine sourceLine = null; - sourceLine = new PulseAudioSourceDataLine(eventLoop); - Line.Info sourceDataLineInfo = sourceLine.getLineInfo(); - - if (DataLine.class.isAssignableFrom(info.getLineClass()) - && info instanceof DataLine.Info) { - System.out - .println("DEBUG: trying to find data line with last matching format"); - - DataLine.Info dataLineInfo = (DataLine.Info) info; - // need to find the DataLine with the last valid format - AudioFormat[] wantedFormats = dataLineInfo.getFormats(); - AudioFormat[] availableFormats = ((DataLine.Info) sourceDataLineInfo) - .getFormats(); - for (int i = wantedFormats.length - 1; i > -1; i--) { - for (AudioFormat aFormat : availableFormats) { - if (wantedFormats[i].matches(aFormat)) { - System.out.println("DEBUG: found a matching format"); - System.out.println("wanted: " + wantedFormats[i]); - System.out.println("available: " + aFormat); - sourceLine.setDefaultFormat(wantedFormats[i]); - sourceLines.add(sourceLine); - return sourceLine; + + if (!isLineSupported(info)) { + throw new IllegalArgumentException("Line unsupported: " + info); + } + + AudioFormat[] formats = null; + AudioFormat defaultFormat = null; + + + if(DataLine.Info.class.isInstance(info)) { + ArrayList<AudioFormat> formatList = new ArrayList<AudioFormat>(); + AudioFormat[] requestedFormats = ((DataLine.Info) info).getFormats(); + for (int i = 0; i< requestedFormats.length; i++) { + AudioFormat f1 = requestedFormats[i]; + for (AudioFormat f2 : getSupportedFormats()){ + + if(f1.matches(f2)) { + formatList.add(f2); + defaultFormat = f1; } } } - - System.out.println("DEBUG: no matches found"); - // no format matches, so return any line - throw new IllegalArgumentException("No matching format found"); - - } - - if (info.matches(sourceDataLineInfo)) { - sourceLines.add(sourceLine); - return sourceLine; + formats = formatList.toArray(new AudioFormat[0]); + + } else { + formats = getSupportedFormats(); + defaultFormat = new AudioFormat(Encoding.PCM_UNSIGNED, 22050, 8, 2, + 2, AudioSystem.NOT_SPECIFIED, false); } - // if (info.matches(_targetDataLineInfo)) { - // PulseAudioTargetDataLine targetLine = new PulseAudioTargetDataLine(); - // _targetLines.add(targetLine); - // return targetLine; - // } - PulseAudioClip clip = new PulseAudioClip(); + if ((info.getLineClass() == SourceDataLine.class)) { + return new PulseAudioSourceDataLine(eventLoop, formats, defaultFormat); + } + + /*if ((info.getLineClass() == TargetDataLine.class)) { + return new PulseAudioTargetDataLine(this, (DataLine.Info) info); + }*/ - if (info.matches(clip.getLineInfo())) { - clips.add(clip); - return clip; - } - - - throw new IllegalArgumentException(); + PulseAudioClip clip = new PulseAudioClip(); + + if (info.matches(clip.getLineInfo())) { + clips.add(clip); + return clip; + } + + throw new IllegalArgumentException(); + + + + + } + @Override public int getMaxLines(javax.sound.sampled.Line.Info info) { return AudioSystem.NOT_SPECIFIED; @@ -166,31 +347,24 @@ return PulseAudioMixerInfo.getInfo(); } - @Override public javax.sound.sampled.Line.Info[] getSourceLineInfo() { - if (isOpen) { - SourceDataLine sourceLine = new PulseAudioSourceDataLine(eventLoop); - Line.Info[] info = new Line.Info[] { sourceLine.getLineInfo() }; - return info; - } - - // if not open, then return empty array - return new Line.Info[] {}; + Line.Info[] localArray = new Line.Info[sourceLineInfos.length]; + System.arraycopy(sourceLineInfos, 0, localArray, 0, sourceLineInfos.length); + return localArray; } @Override public javax.sound.sampled.Line.Info[] getSourceLineInfo( javax.sound.sampled.Line.Info info) { - Line.Info sourceInfo = new Line.Info(PulseAudioSourceDataLine.class); - if (info.matches(sourceInfo)) { - Line.Info[] sourceInfos = { sourceInfo, }; - return sourceInfos; - } else { - Line.Info[] sourceInfos = {}; - return sourceInfos; + ArrayList<javax.sound.sampled.Line.Info> infos = new ArrayList<javax.sound.sampled.Line.Info>(); - } - } + for (Line.Info supportedInfo : sourceLineInfos) { + if (info.matches(supportedInfo)) { + infos.add(supportedInfo); + } + } + return infos.toArray(new Line.Info[infos.size()]); + } @Override public Line[] getSourceLines() { @@ -201,21 +375,22 @@ @Override public javax.sound.sampled.Line.Info[] getTargetLineInfo() { - Line.Info[] info = { new Line.Info(PulseAudioTargetDataLine.class), }; - return info; + Line.Info[] localArray = new Line.Info[targetLineInfos.length]; + System.arraycopy(targetLineInfos, 0, localArray, 0, targetLineInfos.length); + return localArray; } @Override public javax.sound.sampled.Line.Info[] getTargetLineInfo( javax.sound.sampled.Line.Info info) { - Line.Info sourceInfo = new Line.Info(PulseAudioTargetDataLine.class); - if (info.matches(sourceInfo)) { - Line.Info[] sourceInfos = { sourceInfo, }; - return sourceInfos; - } else { - Line.Info[] sourceInfos = {}; - return sourceInfos; - } + ArrayList<javax.sound.sampled.Line.Info> infos = new ArrayList<javax.sound.sampled.Line.Info>(); + + for (Line.Info supportedInfo : targetLineInfos) { + if (info.matches(supportedInfo)) { + infos.add(supportedInfo); + } + } + return infos.toArray(new Line.Info[infos.size()]); } @Override @@ -226,10 +401,21 @@ @Override public boolean isLineSupported(javax.sound.sampled.Line.Info info) { - // if ( _sourceDataLineInfo.matches(info)) { - // return true; - // } - return false; + if (info != null) { + for (int i = 0; i < sourceLineInfos.length; i++) { + if (info.matches(sourceLineInfos[i])) { + return true; + } + } + + for (int i = 0; i < targetLineInfos.length; i++) { + if (info.matches(targetLineInfos[i])) { + return true; + } + } + } + return false; + } @Override @@ -455,46 +641,22 @@ } } - PulseAudioMixer selectedMixer = (PulseAudioMixer) AudioSystem + PulseAudioMixer mixer = (PulseAudioMixer) AudioSystem .getMixer(selectedMixerInfo); - selectedMixer.open(); - SourceDataLine line = (SourceDataLine) selectedMixer - .getLine(new Line.Info(PulseAudioSourceDataLine.class)); - - System.out.println("got a line"); - - // File soundFile = new File(new java.io.File(".").getCanonicalPath() + - // "/testsounds/logout.wav"); - File soundFile = new File( - "/home/iivan/workspace/pulseaudio/testsounds/logout.wav"); + mixer.open(); + File soundFile = new File("testsounds/startup.wav"); AudioInputStream audioInputStream = AudioSystem .getAudioInputStream(soundFile); AudioFormat audioFormat = audioInputStream.getFormat(); - line.open(audioFormat); - line.start(); - PulseAudioStreamVolumeControl control = (PulseAudioStreamVolumeControl) line - .getControl(FloatControl.Type.VOLUME); - PulseAudioStreamMuteControl mute = (PulseAudioStreamMuteControl) line - .getControl(BooleanControl.Type.MUTE); - mute.setValue(true); - control.setValue(40000); - mute.setValue(false); - System.out.println("Volume set to " + control.getValue()); - byte[] abData = new byte[1000]; - int bytesRead = 0; + SourceDataLine line; + line = (SourceDataLine) mixer.getLine(new DataLine.Info( + SourceDataLine.class, audioFormat)); - while (bytesRead >= 0) { - bytesRead = audioInputStream.read(abData, 0, abData.length); - if (bytesRead > 0) { - line.write(abData, 0, bytesRead); - } - } - - System.out.println("about to close"); - line.flush(); - selectedMixer.close(); + line.open(); + System.out.println(line.getFormat().matches(audioFormat)); + mixer.close(); }
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java Wed Aug 13 13:17:13 2008 -0400 +++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java Wed Aug 13 14:22:35 2008 -0400 @@ -69,7 +69,7 @@ private boolean isOpen = false; private boolean isPaused = false; - private List<AudioFormat> supportedFormats = null; + private AudioFormat[] supportedFormats = null; private AudioFormat currentFormat = null; private AudioFormat defaultFormat = null; @@ -112,202 +112,26 @@ static { try { - String library = new java.io.File(".").getCanonicalPath() - + java.io.File.separatorChar + String library = new java.io.File(".").getCanonicalPath() + java.io.File.separatorChar + System.mapLibraryName("pulse-java"); System.out.println(library); System.load(library); } catch (IOException e) { assert ("Loading failed".endsWith("library")); } - } - public PulseAudioSourceDataLine(EventLoop eventLoop) { + public PulseAudioSourceDataLine(EventLoop eventLoop, AudioFormat[] formats, AudioFormat defaultFormat) { + if (formats == null) { + + } + + supportedFormats = formats; this.eventLoop = eventLoop; this.lineListeners = new ArrayList<LineListener>(); this.volume = PulseAudioVolumeControl.MAX_VOLUME; - - /* - * FIXME puselaudio supports any sample rate (it can covert between - * sample rates without a problem). it calculates the frame size and the - * frame rate based on that. - * - * Java's AudioSystem interface accepts NOT_SPECIFIED only for sample - * rate and frame rate. eg: cant say that it supports any number of - * audio channels - * - * sample size in bytes [PA_SAMPLE_U8] = 1, [PA_SAMPLE_ULAW] = 1, - * [PA_SAMPLE_ALAW] = 1, [PA_SAMPLE_S16LE] = 2, [PA_SAMPLE_S16BE] = 2, - * [PA_SAMPLE_FLOAT32LE] = 4, [PA_SAMPLE_FLOAT32BE] = 4, - * [PA_SAMPLE_S32LE] = 4, [PA_SAMPLE_S32BE] = 4, - * - * - */ - - supportedFormats = new LinkedList<AudioFormat>(); - - Map<String, Object> properties; - - int[] channelSizes = new int[] { 1, 2, 5 }; - for (int channelSize : channelSizes) { - properties = new HashMap<String, Object>(); - properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_U8"); - - // frameSize = sample size (in bytes, not bits) x # of channels - // ^ that's from PulseAudio sources, so it will pretty much break - // as soon as they change something - // FIXME ^ - int sampleSize = 8; // in bits - AudioFormat PA_SAMPLE_U8 = new AudioFormat(Encoding.PCM_UNSIGNED, // encoding - AudioSystem.NOT_SPECIFIED, // sample rate - sampleSize, // sample size - channelSize, // channels - sampleSize / 8 * channelSize, // frame size in bytes - AudioSystem.NOT_SPECIFIED, // frame rate - false, // big endian? - properties); - - supportedFormats.add(PA_SAMPLE_U8); - } - - for (int channelSize : channelSizes) { - properties = new HashMap<String, Object>(); - properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_ALAW"); - - // frameSize = sample size (in bytes, not bits) x # of channels - // ^ that's from PulseAudio sources, so it will pretty much break - // as soon as they change something - // FIXME ^ - - int sampleSize = 8; - final AudioFormat PA_SAMPLE_ALAW = new AudioFormat(Encoding.ALAW, // encoding - AudioSystem.NOT_SPECIFIED, // sample rate - sampleSize, // sample size - channelSize, // channels - sampleSize / 8 * channelSize, // frame size - AudioSystem.NOT_SPECIFIED, // frame rate - false, // big endian? - properties); - - supportedFormats.add(PA_SAMPLE_ALAW); - } - - for (int channelSize : channelSizes) { - properties = new HashMap<String, Object>(); - properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_ULAW"); - - // frameSize = sample size (in bytes, not bits) x # of channels - // ^ that's from PulseAudio sources, so it will pretty much break - // as soon as they change something - // FIXME ^ - - int sampleSize = 8; - final AudioFormat PA_SAMPLE_ULAW = new AudioFormat(Encoding.ULAW, // encoding - AudioSystem.NOT_SPECIFIED, // sample rate - sampleSize, // sample size - channelSize, // channels - sampleSize / 8 * channelSize, // frame size - AudioSystem.NOT_SPECIFIED, // frame rate - false, // big endian? - properties); - - supportedFormats.add(PA_SAMPLE_ULAW); - } - - for (int channelSize : channelSizes) { - properties = new HashMap<String, Object>(); - properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S16BE"); - - // frameSize = sample size (in bytes, not bits) x # of channels - // ^ that's from PulseAudio sources, so it will pretty much break - // as soon as they change something - // FIXME ^ - - int sampleSize = 16; - final AudioFormat PA_SAMPLE_S16BE = new AudioFormat( - Encoding.PCM_SIGNED, // encoding - AudioSystem.NOT_SPECIFIED, // sample rate - sampleSize, // sample size - channelSize, // channels - sampleSize / 8 * channelSize, // frame size - AudioSystem.NOT_SPECIFIED, // frame rate - true, // big endian? - properties); - - supportedFormats.add(PA_SAMPLE_S16BE); - } - - for (int channelSize : channelSizes) { - properties = new HashMap<String, Object>(); - properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S16LE"); - - // frameSize = sample size (in bytes, not bits) x # of channels - // ^ that's from PulseAudio sources, so it will pretty much break - // as soon as they change something - // FIXME ^ - - int sampleSize = 16; - final AudioFormat A_SAMPLE_S16LE = new AudioFormat( - Encoding.PCM_SIGNED, // encoding - AudioSystem.NOT_SPECIFIED, // sample rate - sampleSize, // sample size - channelSize, // channels - sampleSize / 8 * channelSize, // frame size - AudioSystem.NOT_SPECIFIED, // frame rate - false, // big endian? - properties); - - supportedFormats.add(A_SAMPLE_S16LE); - } - - for (int channelSize : channelSizes) { - properties = new HashMap<String, Object>(); - properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S32BE"); - - // frameSize = sample size (in bytes, not bits) x # of channels - // ^ that's from PulseAudio sources, so it will pretty much break - // as soon as they change something - // FIXME ^ - - int sampleSize = 32; - final AudioFormat PA_SAMPLE_S32BE = new AudioFormat( - Encoding.PCM_SIGNED, // encoding - AudioSystem.NOT_SPECIFIED, // sample rate - sampleSize, // sample size - channelSize, // channels - sampleSize / 8 * channelSize, // frame size - AudioSystem.NOT_SPECIFIED, // frame rate - true, // big endian? - properties); - - supportedFormats.add(PA_SAMPLE_S32BE); - } - - for (int channelSize : channelSizes) { - properties = new HashMap<String, Object>(); - properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S32LE"); - - // frameSize = sample size (in bytes, not bits) x # of channels - // ^ that's from PulseAudio sources, so it will pretty much break - // as soon as they change something - // FIXME ^ - - int sampleSize = 32; - final AudioFormat PA_SAMPLE_S32LE = new AudioFormat( - Encoding.PCM_SIGNED, // encoding - AudioSystem.NOT_SPECIFIED, // sample rate - sampleSize, // sample size - channelSize, // channels - sampleSize / 8 * channelSize, // frame size - AudioSystem.NOT_SPECIFIED, // frame rate - false, // big endian? - properties); - - supportedFormats.add(PA_SAMPLE_S32LE); - } - - currentFormat = null; + this.defaultFormat = defaultFormat; + this.currentFormat = defaultFormat; } @@ -622,8 +446,9 @@ } public javax.sound.sampled.Line.Info getLineInfo() { - return new DataLine.Info(SourceDataLine.class, supportedFormats - .toArray(new AudioFormat[0]), 0, 100000); + /*return new DataLine.Info(SourceDataLine.class, supportedFormats + .toArray(new AudioFormat[0]), 0, 100000);*/ + return null; } public boolean isControlSupported(Type control) {
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.java Wed Aug 13 13:17:13 2008 -0400 +++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.java Wed Aug 13 14:22:35 2008 -0400 @@ -17,8 +17,10 @@ static { try { String library = new java.io.File(".").getCanonicalPath() + + java.io.File.separatorChar + System.mapLibraryName("pulse-java"); + System.out.println(library); System.load(library); } catch (IOException e) {
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java Wed Aug 13 13:17:13 2008 -0400 +++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java Wed Aug 13 14:22:35 2008 -0400 @@ -39,18 +39,32 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import javax.sound.sampled.*; +import javax.sound.sampled.AudioFormat.Encoding; import javax.sound.sampled.Control.Type; public class PulseAudioTargetDataLine implements TargetDataLine { + protected long contextPointer; protected long mainLoopPointer; protected long streamPointer; protected boolean isOpen = false; protected boolean isPaused = false; protected int defaultBufferSize; + + + private static final int DEFAULT_BUFFER_SIZE = 1000; + private static final String PULSEAUDIO_FORMAT_KEY = "PulseAudioFormatKey"; + private List<AudioFormat> supportedFormats = null; + private AudioFormat currentFormat = null; + private EventLoop eventLoop = null; + protected ArrayList<LineListener> listeners; static { @@ -65,6 +79,198 @@ assert ("Loading failed".endsWith("library")); } } + + public PulseAudioTargetDataLine(EventLoop eventLoop) { + this.eventLoop = eventLoop; + this.listeners = new ArrayList<LineListener>(); + + + + + /* + * FIXME puselaudio supports any sample rate (it can covert between + * sample rates without a problem). it calculates the frame size and the + * frame rate based on that. + * + * Java's AudioSystem interface accepts NOT_SPECIFIED only for sample + * rate and frame rate. eg: cant say that it supports any number of + * audio channels + * + * sample size in bytes [PA_SAMPLE_U8] = 1, [PA_SAMPLE_ULAW] = 1, + * [PA_SAMPLE_ALAW] = 1, [PA_SAMPLE_S16LE] = 2, [PA_SAMPLE_S16BE] = 2, + * [PA_SAMPLE_FLOAT32LE] = 4, [PA_SAMPLE_FLOAT32BE] = 4, + * [PA_SAMPLE_S32LE] = 4, [PA_SAMPLE_S32BE] = 4, + * + * + */ + + supportedFormats = new LinkedList<AudioFormat>(); + + Map<String, Object> properties; + + int[] channelSizes = new int[] { 1, 2, 5 }; + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_U8"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + int sampleSize = 8; // in bits + AudioFormat PA_SAMPLE_U8 = new AudioFormat( + Encoding.PCM_UNSIGNED, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size in bytes + AudioSystem.NOT_SPECIFIED, // frame rate + false, // big endian? + properties); + + supportedFormats.add(PA_SAMPLE_U8); + } + + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_ALAW"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + + int sampleSize = 8; + final AudioFormat PA_SAMPLE_ALAW = new AudioFormat(Encoding.ALAW, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size + AudioSystem.NOT_SPECIFIED, // frame rate + false, // big endian? + properties); + + supportedFormats.add(PA_SAMPLE_ALAW); + } + + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_ULAW"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + + int sampleSize = 8; + final AudioFormat PA_SAMPLE_ULAW = new AudioFormat(Encoding.ULAW, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size + AudioSystem.NOT_SPECIFIED, // frame rate + false, // big endian? + properties); + + supportedFormats.add(PA_SAMPLE_ULAW); + } + + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S16BE"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + + int sampleSize = 16; + final AudioFormat PA_SAMPLE_S16BE = new AudioFormat( + Encoding.PCM_SIGNED, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size + AudioSystem.NOT_SPECIFIED, // frame rate + true, // big endian? + properties); + + supportedFormats.add(PA_SAMPLE_S16BE); + } + + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S16LE"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + + int sampleSize = 16; + final AudioFormat A_SAMPLE_S16LE = new AudioFormat( + Encoding.PCM_SIGNED, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size + AudioSystem.NOT_SPECIFIED, // frame rate + false, // big endian? + properties); + + supportedFormats.add(A_SAMPLE_S16LE); + } + + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S32BE"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + + int sampleSize = 32; + final AudioFormat PA_SAMPLE_S32BE = new AudioFormat( + Encoding.PCM_SIGNED, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size + AudioSystem.NOT_SPECIFIED, // frame rate + true, // big endian? + properties); + + supportedFormats.add(PA_SAMPLE_S32BE); + } + + for (int channelSize : channelSizes) { + properties = new HashMap<String, Object>(); + properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S32LE"); + + // frameSize = sample size (in bytes, not bits) x # of channels + // ^ that's from PulseAudio sources, so it will pretty much break + // as soon as they change something + // FIXME ^ + + int sampleSize = 32; + final AudioFormat PA_SAMPLE_S32LE = new AudioFormat( + Encoding.PCM_SIGNED, // encoding + AudioSystem.NOT_SPECIFIED, // sample rate + sampleSize, // sample size + channelSize, // channels + sampleSize / 8 * channelSize, // frame size + AudioSystem.NOT_SPECIFIED, // frame rate + false, // big endian? + properties); + + supportedFormats.add(PA_SAMPLE_S32LE); + } + + currentFormat = null; + + + } public void open(AudioFormat format, int bufferSize) throws LineUnavailableException {
--- a/src/native/org_classpath_icedtea_pulseaudio_Operation.c Wed Aug 13 13:17:13 2008 -0400 +++ b/src/native/org_classpath_icedtea_pulseaudio_Operation.c Wed Aug 13 14:22:35 2008 -0400 @@ -72,7 +72,7 @@ * Signature: ()I */ JNIEXPORT jint JNICALL Java_org_classpath_icedtea_pulseaudio_Operation_native_1get_1state -(JNIEnv* env, jobject obj) { +(JNIEnv *env, jobject obj) { pa_operation* operation = (pa_operation*) getJavaPointer(env, obj, "operationPointer"); int state = pa_operation_get_state(operation);