changeset 134:381f212496eb

2008-09-23 Omair Majid <omajid@redhat.com> * src/java/org/classpath/icedtea/pulseaudio/Operation.java (waitForComplete): Handles interrupts now. Maybe not the best way of handling them, but it works. * src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java (ClipThread.run): Drain the stream by using the stream functions, not by a call to drain. (drain): Fixed to work the way reported in the bug report. * unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java (testLoopStartStopClip): Renamed to testLoop4Times. Now uses drain to wait for the loop to complete playing. (testDrainWithoutStart): Added a timeout. (testDrainBlocksWhilePlaying): New function. Tests that drain() blocks while playing. (testLoop0Clip): Renamed to testLoop0InterruptsPlayback. (testFramePosition): New function. Checks the value of getLongFrames() from clip. (testFramePositionAfterLooping): Checks that Looping the clip still returns the correct number of frames played (not just the current frame position in the audio stream).
author Omair Majid <omajid@redhat.com>
date Tue, 23 Sep 2008 11:38:18 -0400
parents 4a1c8f3d1f62
children c46f6e0e7959
files src/java/org/classpath/icedtea/pulseaudio/Operation.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java
diffstat 3 files changed, 130 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/src/java/org/classpath/icedtea/pulseaudio/Operation.java	Tue Sep 23 10:29:27 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/Operation.java	Tue Sep 23 11:38:18 2008 -0400
@@ -133,6 +133,8 @@
 
 	public void waitForCompletion() {
 		assert (operationPointer != null);
+
+		boolean interrupted = false;
 		do {
 			synchronized (eventLoop.threadLock) {
 				if (getState() == Operation.State.Done) {
@@ -141,10 +143,15 @@
 				try {
 					eventLoop.threadLock.wait();
 				} catch (InterruptedException e) {
-					e.printStackTrace();
+					// ingore the interrupt for now
+					interrupted = true;
 				}
 			}
 		} while (getState() != State.Done);
 
+		// let the caller know about the interrupt
+		if (interrupted) {
+			Thread.currentThread().interrupt();
+		}
 	}
 }
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java	Tue Sep 23 10:29:27 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java	Tue Sep 23 11:38:18 2008 -0400
@@ -104,7 +104,15 @@
 
 			}
 
-			PulseAudioClip.this.drain();
+			Operation operation;
+
+			synchronized (eventLoop.threadLock) {
+				operation = stream.drain();
+			}
+
+			operation.waitForCompletion();
+			operation.releaseReference();
+
 		}
 	}
 
@@ -209,19 +217,29 @@
 
 	}
 
+	/*
+	 * 
+	 * drain() on a Clip should block until the entire clip has finished playing
+	 * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4732218
+	 * 
+	 * 
+	 * @see org.classpath.icedtea.pulseaudio.PulseAudioDataLine#drain()
+	 */
 	@Override
 	public void drain() {
 		if (!isOpen) {
 			throw new IllegalStateException("line not open");
 		}
 
-		if (clipThread != null) {
-			clipThread.interrupt();
+		while (clipThread != null && clipThread.isAlive()) {
 			try {
 				clipThread.join();
 			} catch (InterruptedException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
 			}
 		}
+
 		Operation operation;
 
 		synchronized (eventLoop.threadLock) {
--- a/unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java	Tue Sep 23 10:29:27 2008 -0400
+++ b/unittests/org/classpath/icedtea/pulseaudio/PulseAudioClipTest.java	Tue Sep 23 11:38:18 2008 -0400
@@ -116,8 +116,12 @@
 	}
 
 	@Test
-	public void testLoopStopStartClip() throws LineUnavailableException,
-			IOException, UnsupportedAudioFileException {
+	public void testLoop4Times() throws LineUnavailableException, IOException,
+			UnsupportedAudioFileException {
+		System.out
+				.println("This tests loop(4) on the Clip. "
+						+ "You should hear a certain part of the clip play back 5 time");
+
 		Clip clip = (Clip) mixer.getLine(new Line.Info(Clip.class));
 		File soundFile = new File("testsounds/startup.wav");
 		AudioInputStream audioInputStream = AudioSystem
@@ -127,18 +131,11 @@
 		clip.setLoopPoints((int) (clip.getFrameLength() / 4), (int) (clip
 				.getFrameLength() / 2));
 		clip.loop(4);
-		try {
-			Thread.sleep(2000);
-		} catch (InterruptedException e) {
-			e.printStackTrace();
-		}
+
+		clip.drain();
+
 		clip.stop();
-		try {
-			Thread.sleep(2000);
-		} catch (InterruptedException e) {
-			e.printStackTrace();
-		}
-		clip.start();
+
 		clip.close();
 	}
 
@@ -280,7 +277,7 @@
 
 	}
 
-	@Test
+	@Test(timeout = 1000)
 	public void testDrainWithoutStart() throws UnsupportedAudioFileException,
 			IOException, LineUnavailableException {
 
@@ -300,7 +297,37 @@
 	}
 
 	@Test
-	public void testLoop0Clip() throws LineUnavailableException, IOException,
+	public void testDrainBlocksWhilePlaying()
+			throws UnsupportedAudioFileException, IOException,
+			LineUnavailableException {
+
+		String fileName = "testsounds/startup.wav";
+		File soundFile = new File(fileName);
+		AudioInputStream audioInputStream = AudioSystem
+				.getAudioInputStream(soundFile);
+		AudioFormat audioFormat = audioInputStream.getFormat();
+
+		Clip clip;
+		clip = (Clip) mixer.getLine(new DataLine.Info(Clip.class, audioFormat));
+		Assert.assertNotNull(clip);
+
+		long startTime = System.currentTimeMillis();
+
+		clip.open(audioInputStream);
+		clip.start();
+		clip.drain();
+		clip.stop();
+		clip.close();
+
+		long endTime = System.currentTimeMillis();
+
+		Assert.assertTrue(endTime - startTime > 3000);
+		System.out.println("Playback of " + fileName + " completed in "
+				+ (endTime - startTime) + " milliseconds");
+	}
+
+	@Test
+	public void testLoop0InterruptsPlayback() throws LineUnavailableException, IOException,
 			UnsupportedAudioFileException {
 		Clip clip = (Clip) mixer.getLine(new Line.Info(Clip.class));
 		File soundFile = new File("testsounds/startup.wav");
@@ -383,6 +410,65 @@
 	}
 
 	@Test
+	public void testFramePosition() throws LineUnavailableException,
+			UnsupportedAudioFileException, IOException {
+		System.out
+				.println("This tests if the Clip provides the correct frame position");
+		Clip clip = (Clip) mixer.getLine(new Line.Info(Clip.class));
+		String fileName = "testsounds/logout.wav";
+		File soundFile1 = new File(fileName);
+		AudioInputStream audioInputStream1 = AudioSystem
+				.getAudioInputStream(soundFile1);
+		clip.open(audioInputStream1);
+
+		clip.start();
+
+		clip.drain();
+
+		long pos = clip.getFramePosition();
+
+		clip.close();
+
+		long expected = 136703;
+		long granularity = 100;
+		System.out.println("Frames in " + fileName + ": " + expected);
+		System.out.println("Frame position in clip :" + pos);
+		Assert.assertTrue("Expected: " + expected + " got " + pos, Math
+				.abs(expected - pos) < granularity);
+
+	}
+
+	@Test
+	public void testFramePositionAfterLooping()
+			throws LineUnavailableException, UnsupportedAudioFileException,
+			IOException {
+		System.out
+				.println("This tests if the Clip provides the correct frame position");
+		Clip clip = (Clip) mixer.getLine(new Line.Info(Clip.class));
+		String fileName = "testsounds/logout.wav";
+		File soundFile1 = new File(fileName);
+		AudioInputStream audioInputStream1 = AudioSystem
+				.getAudioInputStream(soundFile1);
+		clip.open(audioInputStream1);
+
+		clip.loop(1);
+
+		clip.drain();
+
+		long pos = clip.getFramePosition();
+
+		clip.close();
+
+		long expected = 136703 * 2;
+		long granularity = 100;
+		System.out.println("Frames in " + fileName + ": " + expected);
+		System.out.println("Frame position in clip :" + pos);
+		Assert.assertTrue("Expected: " + expected + " got " + pos, Math
+				.abs(expected - pos) < granularity);
+
+	}
+
+	@Test
 	public void testMixerKnowsAboutOpenClips() throws LineUnavailableException,
 			UnsupportedAudioFileException, IOException {
 		Clip clip = (Clip) mixer.getLine(new Line.Info(Clip.class));