changeset 145:bfc67049ee9f

2008-09-26 Omair Majid <omajid@redhat.com> merged changes
author Omair Majid <omajid@redhat.com>
date Fri, 26 Sep 2008 11:21:24 -0400
parents 6201d96f7b94 (current diff) d040c92fd62b (diff)
children 313b9ddd2f04
files src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java
diffstat 6 files changed, 139 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- 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);
 			}
 		}
 	}
--- 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<PulseAudioDataLine> 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)); }
+		 */
 
 	}
 
--- 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);
--- 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);
 	}
--- 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() {
--- 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));