# HG changeset patch # User Omair Majid # Date 1222442484 14400 # Node ID bfc67049ee9f377ac74c8556361c208de65d355d # Parent 6201d96f7b9417c894d867ef5c9d68a4c6d2e07b# Parent d040c92fd62b4f57a148e085d7c13581c6b6977c 2008-09-26 Omair Majid merged changes diff -r 6201d96f7b94 -r bfc67049ee9f src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java --- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java Thu Sep 25 14:33:45 2008 -0400 +++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java Fri Sep 26 11:21:24 2008 -0400 @@ -100,7 +100,9 @@ } else { synchronized (clipLock) { currentFrame = startFrame; - loopsLeft--; + if (loopsLeft != Integer.MIN_VALUE) { + loopsLeft--; + } } } @@ -192,17 +194,20 @@ } - protected void connectLine(int bufferSize, Stream masterStream) throws LineUnavailableException{ + protected void connectLine(int bufferSize, Stream masterStream) + throws LineUnavailableException { StreamBufferAttributes bufferAttributes = new StreamBufferAttributes( bufferSize, bufferSize / 2, bufferSize / 2, bufferSize / 2, 0); - if(masterStream != null) { + if (masterStream != null) { synchronized (eventLoop.threadLock) { - stream.connectForPlayback(Stream.DEFAULT_DEVICE, bufferAttributes, masterStream.getStreamPointer()); + stream.connectForPlayback(Stream.DEFAULT_DEVICE, + bufferAttributes, masterStream.getStreamPointer()); } } else { synchronized (eventLoop.threadLock) { - stream.connectForPlayback(Stream.DEFAULT_DEVICE, bufferAttributes, null); + stream.connectForPlayback(Stream.DEFAULT_DEVICE, + bufferAttributes, null); } } } diff -r 6201d96f7b94 -r bfc67049ee9f src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java --- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java Thu Sep 25 14:33:45 2008 -0400 +++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java Fri Sep 26 11:21:24 2008 -0400 @@ -77,21 +77,19 @@ protected Stream stream; private ArrayList synchronizedLines; - public void open(AudioFormat format, int bufferSize) + protected void open(AudioFormat format, int bufferSize) throws LineUnavailableException { if (isOpen) { - throw new IllegalStateException("DataLine is already open"); + throw new IllegalStateException("Line is already open"); } createStream(format); - addStreamListeners(); connect(null, bufferSize); - } - public void createStream(AudioFormat format) + private void createStream(AudioFormat format) throws LineUnavailableException { for (AudioFormat myFormat : supportedFormats) { @@ -104,7 +102,7 @@ } currentFormat = format; - super.open(); + isOpen = true; } } @@ -112,11 +110,11 @@ throw new IllegalArgumentException("Invalid format"); } - System.out.println("Stream " + stream + " created"); + // System.out.println("Stream " + stream + " created"); } - public void addStreamListeners() { + private void addStreamListeners() { Stream.StateListener openCloseListener = new Stream.StateListener() { @Override @@ -124,7 +122,7 @@ synchronized (eventLoop.threadLock) { /* - * Not the order: first we notify all the listeners, and + * Note the order: first we notify all the listeners, and * then return. this means no race conditions when the * listeners are removed before they get called by close * @@ -166,7 +164,7 @@ @Override public void update() { dataWritten = false; - + if (!corked) { fireLineEvent(new LineEvent(PulseAudioDataLine.this, LineEvent.Type.STOP, AudioSystem.NOT_SPECIFIED)); @@ -214,7 +212,7 @@ stream.addCorkListener(corkListener); } - public void connect(Stream masterStream, int bufferSize) + private void connect(Stream masterStream, int bufferSize) throws LineUnavailableException { try { @@ -223,9 +221,9 @@ } } catch (LineUnavailableException e) { // error connecting to the server! - //stream.removePlaybackStartedListener(startedListener); - //stream.removeUnderflowListener(stoppedListener); - //stream.removeStateListener(openCloseListener); + // stream.removePlaybackStartedListener(startedListener); + // stream.removeUnderflowListener(stoppedListener); + // stream.removeStateListener(openCloseListener); stream.free(); stream = null; throw e; @@ -248,7 +246,7 @@ } } - public void open(AudioFormat format) throws LineUnavailableException { + protected void open(AudioFormat format) throws LineUnavailableException { open(format, DEFAULT_BUFFER_SIZE); } @@ -333,11 +331,12 @@ op.waitForCompletion(); op.releaseReference(); isStarted = true; - - /*if (dataWritten) { - fireLineEvent(new LineEvent(PulseAudioDataLine.this, - LineEvent.Type.START, AudioSystem.NOT_SPECIFIED)); - }*/ + + /* + * if (dataWritten) { fireLineEvent(new + * LineEvent(PulseAudioDataLine.this, LineEvent.Type.START, + * AudioSystem.NOT_SPECIFIED)); } + */ } diff -r 6201d96f7b94 -r bfc67049ee9f src/java/org/classpath/icedtea/pulseaudio/PulseAudioLine.java --- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioLine.java Thu Sep 25 14:33:45 2008 -0400 +++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioLine.java Fri Sep 26 11:21:24 2008 -0400 @@ -44,7 +44,6 @@ import javax.sound.sampled.Line; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; -import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.Control.Type; abstract class PulseAudioLine implements Line { @@ -112,13 +111,7 @@ return isOpen; } - @Override - public void open() throws LineUnavailableException { - /*if (isOpen) { - throw new IllegalStateException("Line is already open"); - }*/ - isOpen = true; - } + public void removeLineListener(LineListener listener) { lineListeners.remove(listener); diff -r 6201d96f7b94 -r bfc67049ee9f src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java --- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java Thu Sep 25 14:33:45 2008 -0400 +++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java Fri Sep 26 11:21:24 2008 -0400 @@ -84,6 +84,11 @@ } + @Override + public void open(AudioFormat format) throws LineUnavailableException { + open(format, DEFAULT_BUFFER_SIZE); + } + public byte[] native_setVolume(float value) { return stream.native_setVolume(value); } diff -r 6201d96f7b94 -r bfc67049ee9f src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java --- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java Thu Sep 25 14:33:45 2008 -0400 +++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java Fri Sep 26 11:21:24 2008 -0400 @@ -80,12 +80,18 @@ super.open(format, bufferSize); currentFramePosition = 0; - + PulseAudioMixer parentMixer = PulseAudioMixer.getInstance(); parentMixer.addTargetLine(this); } - protected void connectLine(int bufferSize, Stream masterStream) throws LineUnavailableException{ + @Override + public void open(AudioFormat format) throws LineUnavailableException { + open(format, DEFAULT_BUFFER_SIZE); + } + + protected void connectLine(int bufferSize, Stream masterStream) + throws LineUnavailableException { StreamBufferAttributes bufferAttributes = new StreamBufferAttributes( bufferSize, 0, 0, 0, bufferSize / 10); synchronized (eventLoop.threadLock) { @@ -130,7 +136,8 @@ sizeRead += bytesRead; position += bytesRead; remainingLength -= bytesRead; - currentFramePosition += bytesRead / currentFormat.getFrameSize(); + currentFramePosition += bytesRead + / currentFormat.getFrameSize(); } } @@ -170,7 +177,13 @@ throw new IllegalStateException("Line must be open"); } - // FIXME how to flush a target data line + Operation operation; + synchronized (eventLoop.threadLock) { + operation = stream.flush(); + } + operation.waitForCompletion(); + operation.releaseReference(); + } public int available() { diff -r 6201d96f7b94 -r bfc67049ee9f unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLineTest.java --- a/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLineTest.java Thu Sep 25 14:33:45 2008 -0400 +++ b/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLineTest.java Fri Sep 26 11:21:24 2008 -0400 @@ -55,7 +55,6 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; public class PulseAudioTargetDataLineTest { @@ -67,7 +66,7 @@ int stopped = 0; AudioFormat aSupportedFormat = new AudioFormat( - AudioFormat.Encoding.PCM_UNSIGNED, 44100f, 8, 1, 1, 10, true); + AudioFormat.Encoding.PCM_UNSIGNED, 44100f, 8, 1, 1, 44100f, true); @Before public void setUp() throws LineUnavailableException { @@ -147,6 +146,74 @@ } @Test + public void testOpenWithFormat() throws LineUnavailableException { + System.out.println("This test checks that read() sort of wroks"); + + targetDataLine = (TargetDataLine) mixer.getLine(new Line.Info( + TargetDataLine.class)); + Assert.assertNotNull(targetDataLine); + targetDataLine.open(aSupportedFormat); + + } + + @Test + public void testRead() throws LineUnavailableException { + System.out.println("This test checks that read() sort of wroks"); + + targetDataLine = (TargetDataLine) mixer.getLine(new Line.Info( + TargetDataLine.class)); + Assert.assertNotNull(targetDataLine); + targetDataLine.open(aSupportedFormat); + + byte[] buffer = new byte[1000]; + for (int i = 0; i < buffer.length; i++) { + buffer[i] = 0; + } + targetDataLine.start(); + + targetDataLine.read(buffer, 0, buffer.length); + Assert.assertTrue(buffer[999] != 0); + + buffer = new byte[1000]; + for (int i = 0; i < buffer.length; i++) { + buffer[i] = 0; + } + + targetDataLine.read(buffer, 0, buffer.length - 2); + Assert.assertTrue(buffer[999] == 0); + + targetDataLine.stop(); + targetDataLine.close(); + + } + + @Test(expected = IllegalArgumentException.class) + public void testReadLessThanFrameSize() throws LineUnavailableException { + System.out.println("This test checks that read() throws an exception " + + "when not reading an integral number of frames"); + + targetDataLine = (TargetDataLine) mixer.getLine(new Line.Info( + TargetDataLine.class)); + Assert.assertNotNull(targetDataLine); + AudioFormat breakingFormat = new AudioFormat( + AudioFormat.Encoding.PCM_UNSIGNED, 44100f, 8, 2, 2, 44100f, + true); + targetDataLine.open(breakingFormat); + + byte[] buffer = new byte[1000]; + for (int i = 0; i < buffer.length; i++) { + buffer[i] = 0; + } + targetDataLine.start(); + + targetDataLine.read(buffer, 0, buffer.length - 1); + + targetDataLine.stop(); + targetDataLine.close(); + + } + + @Test public void testDrain() throws LineUnavailableException, InterruptedException { System.out @@ -193,16 +260,31 @@ } - @Ignore @Test - public void testFlush() { + public void testFlush() throws LineUnavailableException { + System.out.println("This test checks that flush() wroks"); + + targetDataLine = (TargetDataLine) mixer.getLine(new Line.Info( + TargetDataLine.class)); + Assert.assertNotNull(targetDataLine); + targetDataLine.open(); + byte[] buffer = new byte[1000]; + for (int i = 0; i < buffer.length; i++) { + buffer[i] = 0; + } + targetDataLine.start(); + + targetDataLine.read(buffer, 0, buffer.length); + targetDataLine.stop(); + targetDataLine.flush(); + targetDataLine.close(); } @Test(expected = IllegalStateException.class) public void testFlushWithoutOpen() throws LineUnavailableException { System.out - .println("This test checks that drain() fails on a line not opened"); + .println("This test checks that flush() fails on a line not opened"); targetDataLine = (TargetDataLine) mixer.getLine(new Line.Info( TargetDataLine.class));