Mercurial > hg > pulseaudio
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;