changeset in /hg/pulseaudio: 2008-08-25 Omair Majid <omajid at redh...

Omair Majid omajid at redhat.com
Wed Aug 27 09:05:26 PDT 2008


changeset 9a4c1d255bc6 in /hg/pulseaudio
details: http://icedtea.classpath.org/hg/pulseaudio?cmd=changeset;node=9a4c1d255bc6
description:
	2008-08-25 Omair Majid <omajid at redhat.com>

	    * src/java/org/classpath/icedtea/pulseaudio/Operation.java
	      (Operation): Added a check for value pointer

	    * src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java
	      Formatting fixes using eclipse's format
	      (connectLine): Parameter bufferSize is now used to chose buffer
	      attributes.
	      (close): Added a synchronized block to protect shared variables.
	      (flush): Likewise.
	    * src/java/org/classpath/icedtea/pulseaudio/PusleAudioDataLine.java
	      (open): Synchronized stream operations. Pass buffer sizes to the
	      connectLine function. Also added checks to ensure that the stream
	      actually connected.
	      (start): Syncrhonized stream operations.
	      (connectLine): changed signature from connectLine() to connectLine(int
	      bufferSize).

	    * src/java/org/classpath/icedtea/pusleaudio/PulseAudioSourceDataLine.java
	      (connectLine): Changed buffer values. Some buffer attributes now guessed
	      from the max buffer size. Synchronized stream operations.
	    * src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java
	      (connectLine): Likewise

	    * src/java/org/classpath/icedtea/pulseaudio/Stream.java
	      (native_pa_stream_connect_record): Added additional parameters for
	      buffers.
	      (addOverflowListener): Synchronized operation.
	      (removeOverflowListener): Likewise.
	      (addUnderflowListener): Likewise.
	      (removeUnderflowListener): Likewise.
	      (addPlaybackStartedListener): Likewise.
	      (removePlaybackStartedListener): Likewise.
	      (addLatencyUpdateListener): Likewise.
	      (removeLatencyUpdateListener): Likewise.
	      (addMovedListener): Likewise.
	      (removeMovedListener): Likewise.
	      (addSuspenedListener): Likewise.
	      (removeSuspenedListener): Likewise.
	      (connectForRecording): Added a paramter to pass in
	      StreamBufferAttributes.

	    * src/java/org/classpath/icedtea/pulseaudio/StreamBufferAttributes.java
	      Fixed SANE_DEFAULT to be a valid numer. Added extra variables to
	      indicate max and min values.

	    * src/native/org_classpath_icedtea_pulseaudio_Stream.c
	      (stream_state_callback): Commented out debug output.
	      (stream_overflow_callback): Likewise.
	      (stream_latency_update_callback): Likewise.
	      (stream_moved_callback): Likewise.
	      (stream_suspeneded_callback): Likewise.
	      (Java_org_classpath_icedtea_pulseaudio_Stream_native_1pa_1stream_1connect_1playback):
	      Using bufferAttributes passed in to connnect the stream. Commented out
	      debug info. Added a check for return value.
	      (Java_org_classpath_icedtea_pulseaudio_Stream_native_1pa_1stream_1connect_1record):
	      Likewise.
	      (Java_org_classpath_icedtea_pulseaudio_Stream_native_1pa_1stream_1get_1buffer_1attr):
	      Fixed constructor method id. Added checks to fail if this happens again.
	      (set_buffer_attr_callback): Checking the new buffer_attr
	      (Java_org_classpath_icedtea_pulseaudio_Stream_native_1pa_1stream_1set_1buffer_1attr):
	      Added tests to check if everything works. Added some debug info.

	    * unittests/org/classpath/icedtea/pusleaudio/PulseSourceDataLineTest.java:
	      (testPlay): Added some debug output for the test

diffstat:

9 files changed, 297 insertions(+), 193 deletions(-)
src/java/org/classpath/icedtea/pulseaudio/Operation.java                |    1 
src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java           |  141 ++++------
src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java       |   87 +++---
src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java |   14 
src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java |    8 
src/java/org/classpath/icedtea/pulseaudio/Stream.java                   |   70 +++-
src/java/org/classpath/icedtea/pulseaudio/StreamBufferAttributes.java   |    8 
src/native/org_classpath_icedtea_pulseaudio_Stream.c                    |  129 ++++++---
unittests/org/classpath/icedtea/pulseaudio/PulseSourceDataLineTest.java |   32 +-

diffs (truncated from 1008 to 500 lines):

diff -r 23c52715cfb2 -r 9a4c1d255bc6 src/java/org/classpath/icedtea/pulseaudio/Operation.java
--- a/src/java/org/classpath/icedtea/pulseaudio/Operation.java	Wed Aug 20 14:27:45 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/Operation.java	Mon Aug 25 12:07:04 2008 -0400
@@ -77,6 +77,7 @@ public class Operation {
 	private native int native_get_state();
 
 	public Operation(long operationPointer) {
+		assert(operationPointer != 0);
 		this.operationPointer = operationPointer;
 		this.eventLoop = EventLoop.getEventLoop();
 	}
diff -r 23c52715cfb2 -r 9a4c1d255bc6 src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java	Wed Aug 20 14:27:45 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioClip.java	Mon Aug 25 12:07:04 2008 -0400
@@ -71,68 +71,64 @@ public class PulseAudioClip extends Puls
 	private static final AudioFormat DEFAULT_FORMAT = new AudioFormat(
 			AudioFormat.Encoding.PCM_UNSIGNED, 22050, 8, 2, 2, 22050 / 2, false);
 
-
-
 	private static final int DEFAULT_BUFFER_SIZE = 0;
 	public static final String DEFAULT_CLIP_NAME = "Clip";
 
 	private Object clipLock = new Object();
 	private boolean clipThreadStarted;
 	private int loopsLeft;
-	private Semaphore clipSemaphore= new Semaphore(1);
+	private Semaphore clipSemaphore = new Semaphore(1);
 
 	private class ClipThread extends Thread {
 		@Override
 		public void run() {
 			clipThreadStarted = true;
-			while(loopsLeft >= 0) {
+			while (loopsLeft >= 0) {
 				writeFrames(currentFrame, endFrame + 1);
-				if(Thread.interrupted()) {
+				if (Thread.interrupted()) {
 					//Thread.currentThread().interrupt();
 					clipThreadStarted = false;
 					return;
 				}
-			
-				
-		
-			try {
-				//if loop(0) has been called from the mainThread,
-				//wait until loopsLeft has been set
-				clipSemaphore.acquire();
-				if(loopsLeft == 0){
+
+				try {
+					//if loop(0) has been called from the mainThread,
+					//wait until loopsLeft has been set
+					clipSemaphore.acquire();
+					if (loopsLeft == 0) {
 						System.out.println("Reading to the end of the file");
-						writeFrames( endFrame, getFrameLength());
+						writeFrames(endFrame, getFrameLength());
 						return;
-				} else {
-					synchronized (clipLock) {
-						currentFrame = startFrame;
-						loopsLeft--;
+					} else {
+						synchronized (clipLock) {
+							currentFrame = startFrame;
+							loopsLeft--;
+						}
 					}
+					clipSemaphore.release();
+				} catch (InterruptedException e) {
+					return;
 				}
-				clipSemaphore.release();
-			} catch (InterruptedException e) {
-					return;
+
 			}
-					
-					
-			}
-		}
-	}
-	
-	private ClipThread clipThread; 
-			
-	
+		}
+	}
+
+	private ClipThread clipThread;
+
 	private void writeFrames(int startingFrame, int lastFrame) {
 
 		int remainingFrames = lastFrame - startingFrame - 1;
-		while(remainingFrames > 0) {
+		while (remainingFrames > 0) {
 			synchronized (eventLoop.threadLock) {
 				int availableSize = stream.getWritableSize();
-				int framesToWrite = Math.min(remainingFrames, availableSize / getFormat().getFrameSize());
-				stream.write(data, currentFrame * getFormat().getFrameSize(), framesToWrite * getFormat().getFrameSize());
+				int framesToWrite = Math.min(remainingFrames, availableSize
+						/ getFormat().getFrameSize());
+				stream.write(data, currentFrame * getFormat().getFrameSize(),
+						framesToWrite * getFormat().getFrameSize());
 				remainingFrames -= framesToWrite;
 				currentFrame += framesToWrite;
-				if(Thread.interrupted()) {
+				if (Thread.interrupted()) {
 					Thread.currentThread().interrupt();
 					break;
 				}
@@ -141,7 +137,6 @@ public class PulseAudioClip extends Puls
 		}
 	}
 
-	
 	static {
 		try {
 			String library = new java.io.File(".").getCanonicalPath()
@@ -154,27 +149,23 @@ public class PulseAudioClip extends Puls
 		}
 	}
 
-	public PulseAudioClip(EventLoop eventLoop, AudioFormat[] formats, AudioFormat defaultFormat) {
+	public PulseAudioClip(EventLoop eventLoop, AudioFormat[] formats,
+			AudioFormat defaultFormat) {
 		supportedFormats = formats;
 		this.eventLoop = eventLoop;
 		this.lineListeners = new ArrayList<LineListener>();
-		this.defaultFormat = defaultFormat; 
+		this.defaultFormat = defaultFormat;
 		this.currentFormat = defaultFormat;
 		clipThread = new ClipThread();
 
 	}
-	
-	protected void connectLine() {
+
+	protected void connectLine(int bufferSize) {
 		StreamBufferAttributes bufferAttributes = new StreamBufferAttributes(
-				StreamBufferAttributes.SANE_DEFAULT,
-				StreamBufferAttributes.SANE_DEFAULT,
-				StreamBufferAttributes.SANE_DEFAULT,
-				StreamBufferAttributes.SANE_DEFAULT,
-				StreamBufferAttributes.SANE_DEFAULT);
-
-		stream.connectForPlayback(null, bufferAttributes);
-	}
-	
+				bufferSize, bufferSize / 2, bufferSize / 2, bufferSize / 2, 0);
+
+		stream.connectForPlayback(Stream.DEFAULT_DEVICE, bufferAttributes);
+	}
 
 	@Override
 	public int available() {
@@ -188,10 +179,12 @@ public class PulseAudioClip extends Puls
 		} catch (InterruptedException e) {
 			e.printStackTrace();
 		}
-		
-		stream.drain();
-		stream.disconnect();
-		isOpen = false;
+
+		synchronized (eventLoop.threadLock) {
+			drain();
+			stream.disconnect();
+			isOpen = false;
+		}
 	}
 
 	@Override
@@ -209,7 +202,9 @@ public class PulseAudioClip extends Puls
 
 	@Override
 	public void flush() {
-		stream.flush();
+		synchronized (eventLoop.threadLock) {
+			stream.flush();
+		}
 	}
 
 	@Override
@@ -260,7 +255,7 @@ public class PulseAudioClip extends Puls
 
 	@Override
 	public long getLongFramePosition() {
-		synchronized(clipLock) {
+		synchronized (clipLock) {
 			return framesSinceOpen;
 		}
 	}
@@ -270,14 +265,14 @@ public class PulseAudioClip extends Puls
 		if (!isOpen) {
 			return AudioSystem.NOT_SPECIFIED;
 		}
-		synchronized(clipLock) {
+		synchronized (clipLock) {
 			return frameCount / currentFormat.getFrameSize();
 		}
 	}
 
 	@Override
 	public long getMicrosecondPosition() {
-		synchronized(clipLock) {
+		synchronized (clipLock) {
 			return framesSinceOpen / currentFormat.getFrameSize();
 		}
 	}
@@ -308,22 +303,22 @@ public class PulseAudioClip extends Puls
 	@Override
 	public void loop(int count) {
 		System.out.println("Loop " + count + " called");
-		if(clipThreadStarted && count != 0) {
+		if (clipThreadStarted && count != 0) {
 			//Do nothing; behavior not specified by the Java API 
 			return;
 		}
-		synchronized(clipLock) {
-			if(currentFrame > endFrame) {
+		synchronized (clipLock) {
+			if (currentFrame > endFrame) {
 				loopsLeft = 0;
 			} else {
-				loopsLeft = count; 
+				loopsLeft = count;
 			}
 		}
 		if (!clipThread.isAlive()) {
 			clipThread = new ClipThread();
 			clipThread.start();
-		} 
-			
+		}
+
 	}
 
 	@Override
@@ -338,7 +333,7 @@ public class PulseAudioClip extends Puls
 		super.open(format);
 		this.data = new byte[bufferSize];
 		System.arraycopy(data, offset, this.data, 0, bufferSize);
-		frameCount =  bufferSize / format.getFrameSize();
+		frameCount = bufferSize / format.getFrameSize();
 		isOpen = true;
 	}
 
@@ -350,7 +345,6 @@ public class PulseAudioClip extends Puls
 		stream.read(buffer, 0, buffer.length);
 
 		open(stream.getFormat(), buffer, 0, buffer.length);
-	
 
 	}
 
@@ -365,8 +359,8 @@ public class PulseAudioClip extends Puls
 		if (frames > frameCount) {
 			throw new IllegalArgumentException("incorreft frame value");
 		}
-		
-		synchronized(clipLock) {
+
+		synchronized (clipLock) {
 			currentFrame = frames;
 		}
 
@@ -383,7 +377,7 @@ public class PulseAudioClip extends Puls
 					"ending point must be greater than or equal to the starting point");
 		}
 
-		synchronized(clipLock) {
+		synchronized (clipLock) {
 			startFrame = start;
 			endFrame = end;
 		}
@@ -393,7 +387,7 @@ public class PulseAudioClip extends Puls
 	@Override
 	public void setMicrosecondPosition(long microseconds) {
 		float frameIndex = microseconds * currentFormat.getFrameRate();
-		synchronized(clipLock) {
+		synchronized (clipLock) {
 			currentFrame = (int) frameIndex;
 		}
 
@@ -401,18 +395,17 @@ public class PulseAudioClip extends Puls
 
 	@Override
 	public void start() {
-		if(!clipThread.isAlive()) {
-			synchronized(clipLock) {
+		if (!clipThread.isAlive()) {
+			synchronized (clipLock) {
 				loopsLeft = 0;
 			}
 			clipThread = new ClipThread();
 			clipThread.start();
 		}
 	}
-	
-	
+
 	public void stop() {
-		if(clipThread.isAlive()) {
+		if (clipThread.isAlive()) {
 			clipThread.interrupt();
 		}
 		try {
@@ -420,7 +413,7 @@ public class PulseAudioClip extends Puls
 		} catch (InterruptedException e) {
 			e.printStackTrace();
 		}
-		synchronized(clipLock) {
+		synchronized (clipLock) {
 			currentFrame = 0;
 			loopsLeft = 0;
 		}
diff -r 23c52715cfb2 -r 9a4c1d255bc6 src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java	Wed Aug 20 14:27:45 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioDataLine.java	Mon Aug 25 12:07:04 2008 -0400
@@ -14,40 +14,38 @@ import javax.sound.sampled.AudioFormat.E
 
 public abstract class PulseAudioDataLine implements Line {
 
-	protected static final int DEFAULT_BUFFER_SIZE = 1000;
+	protected static final int DEFAULT_BUFFER_SIZE = StreamBufferAttributes.SANE_DEFAULT;
 	protected static final String PULSEAUDIO_FORMAT_KEY = "PulseAudioFormatKey";
 
 	protected String streamName = "Java Stream";
-	
+
 	protected boolean isOpen = false;
 	private boolean isPaused = false;
 	protected AudioFormat[] supportedFormats = null;
 	protected AudioFormat currentFormat = null;
 	protected AudioFormat defaultFormat = null;
-	
-	
+
 	protected List<LineListener> lineListeners = new ArrayList<LineListener>();;
-	
+
 	protected EventLoop eventLoop = null;
 	protected Semaphore semaphore = new Semaphore(0);
 	protected Stream stream;
-	
-	
-	
+
 	public void open(AudioFormat format, int bufferSize)
-	throws LineUnavailableException {
+			throws LineUnavailableException {
 		if (isOpen) {
 			throw new IllegalStateException("Line is already open");
 		}
 
-		// ignore suggested buffer size
-
 		for (AudioFormat myFormat : supportedFormats) {
 			if (format.matches(myFormat)) {
-				stream = new Stream(eventLoop.getContextPointer(), streamName,
-						Stream.Format.valueOf((String) myFormat
-								.getProperty(PULSEAUDIO_FORMAT_KEY)),
-								(int) format.getSampleRate(), format.getChannels());
+				synchronized (eventLoop.threadLock) {
+					stream = new Stream(eventLoop.getContextPointer(),
+							streamName, Stream.Format.valueOf((String) myFormat
+									.getProperty(PULSEAUDIO_FORMAT_KEY)),
+							(int) format.getSampleRate(), format.getChannels());
+
+				}
 				currentFormat = format;
 				isOpen = true;
 			}
@@ -61,40 +59,47 @@ public abstract class PulseAudioDataLine
 
 			@Override
 			public void update() {
-				if (stream.getState() == Stream.State.READY) {
-					fireLineEvent(new LineEvent(PulseAudioDataLine.this,
-							LineEvent.Type.OPEN, AudioSystem.NOT_SPECIFIED));
-					semaphore.release();
-				} else if (stream.getState() == Stream.State.TERMINATED
-						|| stream.getState() == Stream.State.FAILED) {
-					fireLineEvent((new LineEvent(PulseAudioDataLine.this,
-							LineEvent.Type.CLOSE, AudioSystem.NOT_SPECIFIED)));
-					semaphore.release();
+				synchronized (eventLoop.threadLock) {
+					if (stream.getState() == Stream.State.READY) {
+						fireLineEvent(new LineEvent(PulseAudioDataLine.this,
+								LineEvent.Type.OPEN, AudioSystem.NOT_SPECIFIED));
+						semaphore.release();
+					} else if (stream.getState() == Stream.State.TERMINATED
+							|| stream.getState() == Stream.State.FAILED) {
+						fireLineEvent((new LineEvent(PulseAudioDataLine.this,
+								LineEvent.Type.CLOSE, AudioSystem.NOT_SPECIFIED)));
+						semaphore.release();
+					}
 				}
 			}
-
 		};
 
 		stream.addStateListener(openCloseListener);
 
 		synchronized (eventLoop.threadLock) {
-
-			connectLine();
+			connectLine(bufferSize);
 		}
 
 		try {
 			semaphore.acquire();
+			synchronized (eventLoop.threadLock) {
+				if (stream.getState() != Stream.State.READY) {
+					stream.disconnect();
+					throw new LineUnavailableException(
+							"unable to obtain a line");
+				}
+			}
 		} catch (InterruptedException e) {
-			// throw new LineUnavailableException("unable to prepare
-			// stream");
+			throw new LineUnavailableException("unable to prepare stream");
 		}
+
 	}
-	
+
 	public void open(AudioFormat format) throws LineUnavailableException {
 		open(format, DEFAULT_BUFFER_SIZE);
 
 	}
-	
+
 	public void open() throws LineUnavailableException {
 		// pick a random format
 		if (defaultFormat == null) {
@@ -105,12 +110,11 @@ public abstract class PulseAudioDataLine
 		open(defaultFormat, DEFAULT_BUFFER_SIZE);
 	}
 
-	
 	public void close() {
 		assert (isOpen);
 
 		synchronized (eventLoop.threadLock) {
-			//drain();
+			// drain();
 			stream.disconnect();
 		}
 
@@ -122,10 +126,12 @@ public abstract class PulseAudioDataLine
 		}
 
 	}
-	
+
 	public void start() {
 		if (isPaused) {
-			stream.cork(false);
+			synchronized (eventLoop.threadLock) {
+				stream.cork(false);
+			}
 			isPaused = false;
 		}
 
@@ -143,7 +149,7 @@ public abstract class PulseAudioDataLine
 		isPaused = true;
 
 	}
-	
+
 	public void addLineListener(LineListener listener) {
 		this.lineListeners.add(listener);
 	}
@@ -151,20 +157,19 @@ public abstract class PulseAudioDataLine
 	public void removeLineListener(LineListener listener) {
 		this.lineListeners.remove(listener);
 	}
-	
+
 	private void fireLineEvent(LineEvent e) {
 		for (LineListener lineListener : lineListeners) {
 			lineListener.update(e);
 		}
 	}
 
-	abstract void connectLine();
+	abstract void connectLine(int bufferSize);
+
 	abstract void drain();
-	
+
 	public boolean isOpen() {
 		return isOpen;
 	}
 



More information about the distro-pkg-dev mailing list