changeset 108:56be77eae7fe

2008-09-04 Omair Majid <omajid@redhat.com> * src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java (close): Delegate the actual closing of the stream to the parent. This handles any synchronization issues in calling the listeners. * src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java (open): Added a test in the beginning. Added a comment explaining how open and close guarenteed that any LineLinsteners are invoked. (close): moved the super.close() to the end of the function to ensure that this class cleans up before it asks the parent class to do so. * src/java/org/classpath/icedtea/pulseaudio/PulseAudioLine.java (close): clear lineListeners. * src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java (close): Added comments explaining the asserts. * unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java (testClipOpenWrongUse): New name for testClipOpen to make the intention clear. There is another test called testClipOpens. (testCloseEvent): Removed the artifical delay after fixing the problem. (testStartedStopped): New function. Test the START and STOP events. * unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLineTest.java (testStartedStopped): New function. Tests PulseAudioTargetDataLine for support of START and STOP events. * unittests/org/classpath/icedtea/pulseaudio/PulseSourceDataLineTest.java (testStartedStopped): Enabled testing of START events.
author Omair Majid <omajid@redhat.com>
date Thu, 04 Sep 2008 14:21:43 -0400
parents 8ddfb8d274c7
children c0fcd9764516
files src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioLine.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLineTest.java unittests/org/classpath/icedtea/pulseaudio/PulseSourceDataLineTest.java
diffstat 7 files changed, 149 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java	Wed Sep 03 15:11:46 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java	Thu Sep 04 14:21:43 2008 -0400
@@ -194,15 +194,11 @@
 			e.printStackTrace();
 		}
 
-		synchronized (eventLoop.threadLock) {
-			drain();
-			stream.disconnect();
-			isOpen = false;
-		}
-
 		PulseAudioMixer mixer = PulseAudioMixer.getInstance();
 		mixer.removeSourceLine(this);
 
+		super.close();
+
 	}
 
 	@Override
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java	Wed Sep 03 15:11:46 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java	Thu Sep 04 14:21:43 2008 -0400
@@ -74,6 +74,10 @@
 	public void open(AudioFormat format, int bufferSize)
 			throws LineUnavailableException {
 
+		if (isOpen) {
+			throw new IllegalStateException("DataLine is already open");
+		}
+
 		for (AudioFormat myFormat : supportedFormats) {
 			if (format.matches(myFormat)) {
 				synchronized (eventLoop.threadLock) {
@@ -97,6 +101,20 @@
 			@Override
 			public void update() {
 				synchronized (eventLoop.threadLock) {
+
+					/*
+					 * Not 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
+					 * 
+					 * eg:
+					 * 
+					 * line.close(); line.removeLineListener(listener)
+					 * 
+					 * the listener is guaranteed to have run
+					 * 
+					 */
+
 					if (stream.getState() == Stream.State.READY) {
 						fireLineEvent(new LineEvent(PulseAudioDataLine.this,
 								LineEvent.Type.OPEN, AudioSystem.NOT_SPECIFIED));
@@ -167,8 +185,6 @@
 
 	public void close() {
 
-		super.close();
-
 		synchronized (eventLoop.threadLock) {
 			drain();
 			stream.disconnect();
@@ -180,6 +196,8 @@
 			throw new RuntimeException("unable to prepare stream");
 		}
 
+		super.close();
+
 	}
 
 	public void start() {
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioLine.java	Wed Sep 03 15:11:46 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioLine.java	Thu Sep 04 14:21:43 2008 -0400
@@ -66,6 +66,8 @@
 			throw new IllegalStateException("Line is not open");
 		}
 
+		lineListeners.clear();
+
 		isOpen = false;
 	}
 
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java	Wed Sep 03 15:11:46 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java	Thu Sep 04 14:21:43 2008 -0400
@@ -448,11 +448,11 @@
 
 		if (sourceLines.size() > 0) {
 			System.out.println("DEBUG: some source lines have not been closed");
-			assert (sourceLines.size() < 0);
+			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);
+			assert (targetLines.size() < 0); // always fail
 		}
 
 		synchronized (lineListeners) {
@@ -596,7 +596,7 @@
 			if (eventLoop.getStatus() != 4) {
 				/*
 				 * when exiting, wait for the thread to end otherwise we get one
-				 * thread that inits the singletone with new data and the old
+				 * thread that inits the singleton with new data and the old
 				 * thread then cleans up the singleton asserts fail all over the
 				 * place
 				 */
--- a/unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java	Wed Sep 03 15:11:46 2008 -0400
+++ b/unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java	Thu Sep 04 14:21:43 2008 -0400
@@ -45,6 +45,7 @@
 import javax.sound.sampled.AudioSystem;
 import javax.sound.sampled.Clip;
 import javax.sound.sampled.Control;
+import javax.sound.sampled.DataLine;
 import javax.sound.sampled.Line;
 import javax.sound.sampled.LineEvent;
 import javax.sound.sampled.LineListener;
@@ -91,7 +92,7 @@
 	}
 
 	@Test(expected = IllegalArgumentException.class)
-	public void testClipOpen() throws LineUnavailableException {
+	public void testClipOpenWrongUse() throws LineUnavailableException {
 		Clip clip = (Clip) mixer.getLine(new Line.Info(Clip.class));
 		clip.open();
 	}
@@ -222,20 +223,70 @@
 		clip.open(audioInputStream);
 		clip.close();
 
-		try {
-			// wait a little while before removing the listener
-			// to ensure it is called before we remove it
-			Thread.sleep(100);
-		} catch (InterruptedException e) {
-			e.printStackTrace();
-		}
 		clip.removeLineListener(closeListener);
 
 		Assert.assertEquals(1, closed);
 
 	}
+	
+	int started = 0;
+	int stopped = 0;
 
 	@Test
+	public void testStartedStopped() throws LineUnavailableException,
+			UnsupportedAudioFileException, IOException {
+
+		File soundFile = new File("testsounds/startup.wav");
+		AudioInputStream audioInputStream = AudioSystem
+				.getAudioInputStream(soundFile);
+		AudioFormat audioFormat = audioInputStream.getFormat();
+
+		Clip clip;
+		clip = (Clip) mixer.getLine(new DataLine.Info(
+				Clip.class, audioFormat));
+		Assert.assertNotNull(clip);
+
+		started = 0;
+		stopped = 0;
+
+		clip.open(audioInputStream);
+
+		LineListener startStopListener = new LineListener() {
+
+			@Override
+			public void update(LineEvent event) {
+				if (event.getType() == LineEvent.Type.START) {
+					started++;
+					Assert.assertEquals(1, started);
+				}
+
+				if (event.getType() == LineEvent.Type.STOP) {
+					System.out.println("Stopped event");
+					stopped++;
+					Assert.assertEquals(1, stopped);
+				}
+			}
+
+		};
+
+		clip.addLineListener(startStopListener);
+
+		clip.start();
+		clip.drain();
+
+		clip.stop();
+		clip.close();
+
+		Assert.assertEquals(1, started);
+		Assert.assertEquals(1, stopped);
+
+		started = 0;
+		stopped = 0;
+
+	}
+	
+	
+	@Test
 	public void testLoop0Clip() throws LineUnavailableException, IOException,
 			UnsupportedAudioFileException {
 		Clip clip = (Clip) mixer.getLine(new Line.Info(Clip.class));
--- a/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLineTest.java	Wed Sep 03 15:11:46 2008 -0400
+++ b/unittests/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLineTest.java	Thu Sep 04 14:21:43 2008 -0400
@@ -1,6 +1,10 @@
 package org.classpath.icedtea.pulseaudio;
 
+import java.io.File;
+import java.io.IOException;
+
 import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
 import javax.sound.sampled.AudioSystem;
 import javax.sound.sampled.DataLine;
 import javax.sound.sampled.Line;
@@ -10,6 +14,7 @@
 import javax.sound.sampled.Mixer;
 import javax.sound.sampled.SourceDataLine;
 import javax.sound.sampled.TargetDataLine;
+import javax.sound.sampled.UnsupportedAudioFileException;
 
 import junit.framework.JUnit4TestAdapter;
 
@@ -129,6 +134,63 @@
 
 	}
 
+	int started = 0;
+	int stopped = 0;
+
+	@Test
+	public void testStartedStopped() throws LineUnavailableException,
+			UnsupportedAudioFileException, IOException {
+
+		File soundFile = new File("testsounds/startup.wav");
+		AudioInputStream audioInputStream = AudioSystem
+				.getAudioInputStream(soundFile);
+		AudioFormat audioFormat = audioInputStream.getFormat();
+
+		TargetDataLine line;
+		line = (TargetDataLine) mixer.getLine(new DataLine.Info(
+				TargetDataLine.class, audioFormat));
+		Assert.assertNotNull(line);
+
+		started = 0;
+		stopped = 0;
+
+		line.open(audioFormat);
+
+		LineListener startStopListener = new LineListener() {
+
+			@Override
+			public void update(LineEvent event) {
+				if (event.getType() == LineEvent.Type.START) {
+					started++;
+					Assert.assertEquals(1, started);
+				}
+
+				if (event.getType() == LineEvent.Type.STOP) {
+					System.out.println("Stopped event");
+					stopped++;
+					Assert.assertEquals(1, stopped);
+				}
+			}
+
+		};
+
+		line.addLineListener(startStopListener);
+
+		line.start();
+
+		line.drain();
+
+		line.stop();
+		line.close();
+
+		Assert.assertEquals(1, started);
+		Assert.assertEquals(1, stopped);
+
+		started = 0;
+		stopped = 0;
+
+	}
+
 	@Test
 	public void testMixerKnowsAboutOpenLines() throws LineUnavailableException {
 		targetDataLine = (TargetDataLine) mixer.getLine(new Line.Info(
--- a/unittests/org/classpath/icedtea/pulseaudio/PulseSourceDataLineTest.java	Wed Sep 03 15:11:46 2008 -0400
+++ b/unittests/org/classpath/icedtea/pulseaudio/PulseSourceDataLineTest.java	Thu Sep 04 14:21:43 2008 -0400
@@ -212,7 +212,7 @@
 		line.stop();
 		line.close();
 
-		// Assert.assertEquals(1, started);
+		Assert.assertEquals(1, started);
 		Assert.assertEquals(1, stopped);
 
 		started = 0;