# HG changeset patch # User Omair Majid # Date 1224005195 14400 # Node ID a28576af0d10c544c49ce971a9e52cd1a658f16e # Parent 9032c6fda5c2cd25fda406957039da9ad870a84d 2008-10-14 Omair Majid * .hgignore: Added generated files to ignore list. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java (EventLoop): Initialize eventLoop object on construction. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java (PulseAudioClip): Removed the parameter eventLoop. (getMicrosecondLength): Return time in microseconds. (getMicrosecondPosition): Likewise. (open): Dont throw an exception if Mixer is not open. Let super handle it. (setFramePosition): Check frame position for being positive. (setLoopPoints): Check that the starting frame is valid. (setMicrosecondPosition): Deal with negative value and values over the maximum. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java (open): Open the mixer if it isnt open. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java (getLine): Dont pass eventLoop as a paramter. (close): Close all open lines on exit. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java (PulseAudioPort): Modified to not take an EventLoop paramter. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java (PulseAudioSourceDataLine): Likewise. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java (PulseAudioSourcePort): Likewise. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java (PulseAudioTargetDataLine): Likewise. * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java (PulseAudioTargetPort): Likewise. * pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLineTest.java (testMixerKnowsAboutOpenLines): Work even if mixer has some lines initially open. diff -r 9032c6fda5c2 -r a28576af0d10 .hgignore --- a/.hgignore Sun Oct 12 16:31:50 2008 +0200 +++ b/.hgignore Tue Oct 14 13:26:35 2008 -0400 @@ -441,3 +441,7 @@ rt/java/io/ rt/sun/awt generated/sun/awt/X11/generator/sizer.32.orig +pulseaudio/bin +pulseaudio/.*\.o +pulseaudio/src/native/org_.*.h +pulseaudio/.*jar diff -r 9032c6fda5c2 -r a28576af0d10 ChangeLog --- a/ChangeLog Sun Oct 12 16:31:50 2008 +0200 +++ b/ChangeLog Tue Oct 14 13:26:35 2008 -0400 @@ -1,3 +1,39 @@ +2008-10-14 Omair Majid + + * .hgignore: Added generated files to ignore list. + + * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java + (EventLoop): Initialize eventLoop object on construction. + + * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java + (PulseAudioClip): Removed the parameter eventLoop. + (getMicrosecondLength): Return time in microseconds. + (getMicrosecondPosition): Likewise. + (open): Dont throw an exception if Mixer is not open. Let super handle it. + (setFramePosition): Check frame position for being positive. + (setLoopPoints): Check that the starting frame is valid. + (setMicrosecondPosition): Deal with negative value and values over the + maximum. + * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java + (open): Open the mixer if it isnt open. + * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java + (getLine): Dont pass eventLoop as a paramter. + (close): Close all open lines on exit. + * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java + (PulseAudioPort): Modified to not take an EventLoop paramter. + * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java + (PulseAudioSourceDataLine): Likewise. + * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java + (PulseAudioSourcePort): Likewise. + * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java + (PulseAudioTargetDataLine): Likewise. + * pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java + (PulseAudioTargetPort): Likewise. + + * pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLineTest.java + (testMixerKnowsAboutOpenLines): Work even if mixer has some lines + initially open. + 2008-10-12 Matthias Klose * Makefile.am (stamps/pulse-java.stamp): Add -I$(ICEDTEA_BOOT_DIR)/include diff -r 9032c6fda5c2 -r a28576af0d10 pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java --- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java Sun Oct 12 16:31:50 2008 +0200 +++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java Tue Oct 14 13:26:35 2008 -0400 @@ -110,7 +110,7 @@ private EventLoop() { contextListeners = new ArrayList(); - + threadLock = new Object(); } synchronized public static EventLoop getEventLoop() { diff -r 9032c6fda5c2 -r a28576af0d10 pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java --- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java Sun Oct 12 16:31:50 2008 +0200 +++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java Tue Oct 14 13:26:35 2008 -0400 @@ -194,10 +194,8 @@ stream.removeWriteListener(writeListener); } - public PulseAudioClip(EventLoop eventLoop, AudioFormat[] formats, - AudioFormat defaultFormat) { + public PulseAudioClip(AudioFormat[] formats, AudioFormat defaultFormat) { supportedFormats = formats; - this.eventLoop = eventLoop; this.defaultFormat = defaultFormat; this.currentFormat = defaultFormat; this.volume = PulseAudioVolumeControl.MAX_VOLUME; @@ -342,7 +340,7 @@ return AudioSystem.NOT_SPECIFIED; } synchronized (clipLock) { - return frameCount / currentFormat.getFrameSize(); + return (long) (frameCount / currentFormat.getFrameRate() * 1000); } } @@ -353,7 +351,7 @@ } synchronized (clipLock) { - return framesSinceOpen / currentFormat.getFrameSize(); + return (long) (framesSinceOpen / currentFormat.getFrameRate() * 1000); } } @@ -398,11 +396,6 @@ public void open(AudioFormat format, byte[] data, int offset, int bufferSize) throws LineUnavailableException { - if(!PulseAudioMixer.getInstance().isOpen()) { - throw new LineUnavailableException("The mixer needs to be opened before opening a line"); - } - - /* check for permission to play audio */ AudioPermission perm = new AudioPermission("play", null); perm.checkGuard(null); @@ -472,7 +465,7 @@ throw new IllegalStateException("Line not open"); } - if (frames > frameCount) { + if (frames < 0 || frames > frameCount) { throw new IllegalArgumentException("incorreft frame value"); } @@ -497,6 +490,11 @@ "ending point must be greater than or equal to the starting point"); } + if (start < 0) { + throw new IllegalArgumentException( + "starting point must be greater than or equal to 0"); + } + synchronized (clipLock) { startFrame = start; endFrame = end; @@ -510,7 +508,16 @@ throw new IllegalStateException("Line not open"); } - float frameIndex = microseconds * currentFormat.getFrameRate(); + float frameIndex = microseconds * currentFormat.getFrameRate() / 1000; + + /* make frameIndex positive */ + while (frameIndex < 0) { + frameIndex += frameCount; + } + + /* frameIndex is in the range [0, frameCount-1], inclusive */ + frameIndex = frameIndex % frameCount; + synchronized (clipLock) { currentFrame = (int) frameIndex; } @@ -563,7 +570,7 @@ super.stop(); } - + public javax.sound.sampled.Line.Info getLineInfo() { return new DataLine.Info(Clip.class, supportedFormats, StreamBufferAttributes.MIN_VALUE, diff -r 9032c6fda5c2 -r a28576af0d10 pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java --- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java Sun Oct 12 16:31:50 2008 +0200 +++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java Tue Oct 14 13:26:35 2008 -0400 @@ -84,10 +84,13 @@ if (isOpen) { throw new IllegalStateException("Line is already open"); } - if(!PulseAudioMixer.getInstance().isOpen()) { - throw new LineUnavailableException("The mixer needs to be opened before opening a line"); + + PulseAudioMixer mixer = PulseAudioMixer.getInstance(); + if(!mixer.isOpen()) { + mixer.open(); } + eventLoop = EventLoop.getEventLoop(); createStream(format); addStreamListeners(); diff -r 9032c6fda5c2 -r a28576af0d10 pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java --- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java Sun Oct 12 16:31:50 2008 +0200 +++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java Tue Oct 14 13:26:35 2008 -0400 @@ -43,6 +43,7 @@ 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; @@ -301,8 +302,7 @@ AudioPermission perm = new AudioPermission("play", null); perm.checkGuard(null); - return new PulseAudioSourceDataLine(eventLoop, formats, - defaultFormat); + return new PulseAudioSourceDataLine(formats, defaultFormat); } if ((info.getLineClass() == TargetDataLine.class)) { @@ -310,8 +310,7 @@ AudioPermission perm = new AudioPermission("record", null); perm.checkGuard(null); - return new PulseAudioTargetDataLine(eventLoop, formats, - defaultFormat); + return new PulseAudioTargetDataLine(formats, defaultFormat); } if ((info.getLineClass() == Clip.class)) { @@ -319,15 +318,15 @@ AudioPermission perm = new AudioPermission("play", null); perm.checkGuard(null); - return new PulseAudioClip(eventLoop, formats, defaultFormat); + return new PulseAudioClip(formats, defaultFormat); } if (Port.Info.class.isInstance(info)) { Port.Info portInfo = (Port.Info) info; if (portInfo.isSource()) { - return new PulseAudioSourcePort(portInfo.getName(), eventLoop); + return new PulseAudioSourcePort(portInfo.getName()); } else { - return new PulseAudioTargetPort(portInfo.getName(), eventLoop); + return new PulseAudioTargetPort(portInfo.getName()); } } @@ -507,6 +506,35 @@ throw new IllegalStateException("Mixer is not open; cant close"); } + List linesToClose = new LinkedList(); + linesToClose.addAll(sourceLines); + if (sourceLines.size() > 0) { + linesToClose.addAll(sourceLines); + for (Line line : linesToClose) { + if (line.isOpen()) { + System.out + .println("PulseAudioMixer: DEBUG: some source lines have not been closed"); + line.close(); + } + } + } + linesToClose.clear(); + + if (targetLines.size() > 0) { + linesToClose.addAll(targetLines); + for (Line line : linesToClose) { + if (line.isOpen()) { + System.out + .println("PulseAudioMixer: DEBUG: some target lines have not been closed"); + line.close(); + } + } + } + + synchronized (lineListeners) { + lineListeners.clear(); + } + eventLoopThread.interrupt(); try { @@ -520,19 +548,6 @@ isOpen = false; - if (sourceLines.size() > 0) { - System.out.println("DEBUG: some source lines have not been closed"); - assert (sourceLines.size() < 0); // always fail - } - if (targetLines.size() > 0) { - System.out.println("DEBUG: some target lines have not been closed"); - assert (targetLines.size() < 0); // always fail - } - - synchronized (lineListeners) { - lineListeners.clear(); - } - refreshSourceAndTargetLines(); } diff -r 9032c6fda5c2 -r a28576af0d10 pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java --- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java Sun Oct 12 16:31:50 2008 +0200 +++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioPort.java Tue Oct 14 13:26:35 2008 -0400 @@ -66,25 +66,25 @@ System.loadLibrary("pulse-java"); } - public PulseAudioPort(String name, EventLoop eventLoop) { + public PulseAudioPort(String name) { this.name = name; + this.eventLoop = EventLoop.getEventLoop(); this.contextPointer = eventLoop.getContextPointer(); - this.eventLoop = eventLoop; + updateVolumeInfo(); volumeControl = new PulseAudioVolumeControl(this, eventLoop); controls.add(volumeControl); muteControl = new PulseAudioMuteControl(this, volumeControl); controls.add(muteControl); - //isOpen = true; - open(); + /* * unlike other lines, Ports must either be open or close * * close = no sound. open = sound * */ - // FIXME open(); + open(); // System.out.println("Opened Target Port " + name); } @@ -141,7 +141,7 @@ @Override public void open() { - if(isOpen) { + if (isOpen) { return; } native_setVolume(volume); diff -r 9032c6fda5c2 -r a28576af0d10 pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java --- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java Sun Oct 12 16:31:50 2008 +0200 +++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java Tue Oct 14 13:26:35 2008 -0400 @@ -54,11 +54,10 @@ private boolean muted; private float volume; - public PulseAudioSourceDataLine(EventLoop eventLoop, AudioFormat[] formats, + public PulseAudioSourceDataLine(AudioFormat[] formats, AudioFormat defaultFormat) { this.supportedFormats = formats; - this.eventLoop = eventLoop; this.lineListeners = new ArrayList(); this.defaultFormat = defaultFormat; this.currentFormat = defaultFormat; @@ -69,7 +68,7 @@ synchronized public void open(AudioFormat format, int bufferSize) throws LineUnavailableException { - /* check for permmission to play audio */ + /* check for permission to play audio */ AudioPermission perm = new AudioPermission("play", null); perm.checkGuard(null); diff -r 9032c6fda5c2 -r a28576af0d10 pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java --- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java Sun Oct 12 16:31:50 2008 +0200 +++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourcePort.java Tue Oct 14 13:26:35 2008 -0400 @@ -43,43 +43,43 @@ public class PulseAudioSourcePort extends PulseAudioPort { /* aka mic */ - + static { System.loadLibrary("pulse-java"); } - public PulseAudioSourcePort(String name, EventLoop eventLoop) { - super(name, eventLoop); + public PulseAudioSourcePort(String name) { + super(name); } public void open() { - + /* check for permission to record audio */ AudioPermission perm = new AudioPermission("record", null); perm.checkGuard(null); - + super.open(); - + PulseAudioMixer parent = PulseAudioMixer.getInstance(); parent.addSourceLine(this); } - + public void close() { - + /* check for permission to record audio */ AudioPermission perm = new AudioPermission("record", null); perm.checkGuard(null); - + if (!isOpen) { throw new IllegalStateException("Port is not open; so cant close"); } - + PulseAudioMixer parent = PulseAudioMixer.getInstance(); parent.removeSourceLine(this); - - super.close(); + + super.close(); } - + public native byte[] native_setVolume(float newValue); public synchronized native byte[] native_updateVolumeInfo(); @@ -88,7 +88,5 @@ public javax.sound.sampled.Line.Info getLineInfo() { return new Port.Info(Port.class, getName(), false); } - - } diff -r 9032c6fda5c2 -r a28576af0d10 pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java --- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java Sun Oct 12 16:31:50 2008 +0200 +++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java Tue Oct 14 13:26:35 2008 -0400 @@ -61,10 +61,9 @@ boolean flushed = false; boolean drained = false; - public PulseAudioTargetDataLine(EventLoop eventLoop, AudioFormat[] formats, + public PulseAudioTargetDataLine(AudioFormat[] formats, AudioFormat defaultFormat) { supportedFormats = formats; - this.eventLoop = eventLoop; this.defaultFormat = defaultFormat; this.currentFormat = defaultFormat; @@ -363,7 +362,7 @@ fireLineEvent(new LineEvent(this, LineEvent.Type.STOP, framesSinceOpen)); } - + public javax.sound.sampled.Line.Info getLineInfo() { return new DataLine.Info(TargetDataLine.class, supportedFormats, StreamBufferAttributes.MIN_VALUE, diff -r 9032c6fda5c2 -r a28576af0d10 pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java --- a/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java Sun Oct 12 16:31:50 2008 +0200 +++ b/pulseaudio/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetPort.java Tue Oct 14 13:26:35 2008 -0400 @@ -48,9 +48,9 @@ System.loadLibrary("pulse-java"); } - public PulseAudioTargetPort(String name, EventLoop eventLoop) { + public PulseAudioTargetPort(String name) { - super(name, eventLoop); + super(name); } public void open() { @@ -70,11 +70,11 @@ /* check for permission to play audio */ AudioPermission perm = new AudioPermission("play", null); perm.checkGuard(null); - + if (!isOpen) { throw new IllegalStateException("not open, so cant close Port"); } - + PulseAudioMixer parent = PulseAudioMixer.getInstance(); parent.removeTargetLine(this); diff -r 9032c6fda5c2 -r a28576af0d10 pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLineTest.java --- a/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLineTest.java Sun Oct 12 16:31:50 2008 +0200 +++ b/pulseaudio/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLineTest.java Tue Oct 14 13:26:35 2008 -0400 @@ -536,11 +536,11 @@ targetDataLine = (TargetDataLine) mixer.getLine(new Line.Info( TargetDataLine.class)); - Assert.assertEquals(0, mixer.getTargetLines().length); + int initiallyOpen = mixer.getTargetLines().length; targetDataLine.open(); - Assert.assertEquals(1, mixer.getTargetLines().length); + Assert.assertEquals(initiallyOpen+1, mixer.getTargetLines().length); targetDataLine.close(); - Assert.assertEquals(0, mixer.getTargetLines().length); + Assert.assertEquals(initiallyOpen, mixer.getTargetLines().length); }