changeset 72:3003bf4192f2

src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java: the list of formats recognized by PulseAudio is being set here, so it can be used by all DataLines. Also made some changes to get*LineInfo() and isLineSupported() src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java: changed the constructor
author Ioana Ivan
date Wed, 13 Aug 2008 14:22:35 -0400
parents 9ed589465932
children 20b37b004b8e
files ChangeLog build.xml src/java/org/classpath/icedtea/pulseaudio/EventLoop.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.java src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java src/native/org_classpath_icedtea_pulseaudio_Operation.c
diffstat 8 files changed, 508 insertions(+), 301 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Aug 13 13:17:13 2008 -0400
+++ b/ChangeLog	Wed Aug 13 14:22:35 2008 -0400
@@ -1,3 +1,13 @@
+2008-08-13 Ioana Ivan  <iivan@redhat.com>
+
+        * src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java: the
+	list of formats recognized by PulseAudio is being set here, so it can
+	be used by all DataLines. Also made some changes to get*LineInfo() and
+	isLineSupported()
+	*src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java:
+	changed the constructor 
+
+
 2008-08-11  Joshua Sumali  <jsumali@redhat.com>
 
 	* configure.ac: Add check for libpulse.
--- a/build.xml	Wed Aug 13 13:17:13 2008 -0400
+++ b/build.xml	Wed Aug 13 14:22:35 2008 -0400
@@ -40,6 +40,7 @@
 			<class name="org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine"/>
 			<class name="org.classpath.icedtea.pulseaudio.PulseAudioClip"/>
 			<class name="org.classpath.icedtea.pulseaudio.PulseAudioStreamVolumeControl"/>
+			<class name="org.classpath.icedtea.pulseaudio.Operation"/>
 		</javah>
 	</target>
 
--- a/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java	Wed Aug 13 13:17:13 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/EventLoop.java	Wed Aug 13 14:22:35 2008 -0400
@@ -105,6 +105,7 @@
 	static {
 		try {
 			String library = new java.io.File(".").getCanonicalPath()
+
 					+ java.io.File.separatorChar
 					+ System.mapLibraryName("pulse-java");
 			System.out.println(library);
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java	Wed Aug 13 13:17:13 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java	Wed Aug 13 14:22:35 2008 -0400
@@ -41,7 +41,10 @@
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.Semaphore;
 
 import javax.sound.sampled.AudioFormat;
@@ -57,17 +60,25 @@
 import javax.sound.sampled.LineUnavailableException;
 import javax.sound.sampled.Mixer;
 import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.TargetDataLine;
+import javax.sound.sampled.AudioFormat.Encoding;
 import javax.sound.sampled.Control.Type;
 
+
+
 public class PulseAudioMixer implements javax.sound.sampled.Mixer {
 	// singleton
 
 	public EventLoop eventLoop;
 	public Thread eventLoopThread;
+	
+	private Line.Info[] sourceLineInfos;
+	private Line.Info[] targetLineInfos;
 
 	private static PulseAudioMixer _instance = null;
 
 	private static final String DEFAULT_APP_NAME = "Java App";
+	private static final String PULSEAUDIO_FORMAT_KEY = "PulseAudioFormatKey";
 
 	private boolean isOpen = false;
 
@@ -83,6 +94,9 @@
 	private PulseAudioMixer() {
 		lineListeners = new ArrayList<LineListener>();
 		sourceLines = new ArrayList<PulseAudioSourceDataLine>();
+		AudioFormat[] formats = getSupportedFormats();
+		sourceLineInfos = new Line.Info[] {new DataLine.Info(SourceDataLine.class, formats, AudioSystem.NOT_SPECIFIED, AudioSystem.NOT_SPECIFIED)};
+		targetLineInfos = new Line.Info[] {new DataLine.Info(TargetDataLine.class, formats, AudioSystem.NOT_SPECIFIED, AudioSystem.NOT_SPECIFIED)};
 		// _targetLines = new ArrayList<PulseAudioTargetDataLine>();
 	}
 
@@ -93,6 +107,174 @@
 		return _instance;
 	}
 
+private AudioFormat[] getSupportedFormats() {
+		
+		List<AudioFormat> supportedFormats = new ArrayList<AudioFormat>();
+
+		Map<String, Object> properties;
+
+		int[] channelSizes = new int[] { 1, 2, 5 };
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_U8");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+			int sampleSize = 8; // in bits
+			AudioFormat PA_SAMPLE_U8 = new AudioFormat(Encoding.PCM_UNSIGNED, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size in bytes
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					false, // big endian?
+					properties);
+
+			supportedFormats.add(PA_SAMPLE_U8);
+		}
+
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_ALAW");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+
+			int sampleSize = 8;
+			final AudioFormat PA_SAMPLE_ALAW = new AudioFormat(Encoding.ALAW, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					false, // big endian?
+					properties);
+
+			supportedFormats.add(PA_SAMPLE_ALAW);
+		}
+
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_ULAW");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+
+			int sampleSize = 8;
+			final AudioFormat PA_SAMPLE_ULAW = new AudioFormat(Encoding.ULAW, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					false, // big endian?
+					properties);
+
+			supportedFormats.add(PA_SAMPLE_ULAW);
+		}
+
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S16BE");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+
+			int sampleSize = 16;
+			final AudioFormat PA_SAMPLE_S16BE = new AudioFormat(
+					Encoding.PCM_SIGNED, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					true, // big endian?
+					properties);
+
+			supportedFormats.add(PA_SAMPLE_S16BE);
+		}
+
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S16LE");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+
+			int sampleSize = 16;
+			final AudioFormat A_SAMPLE_S16LE = new AudioFormat(
+					Encoding.PCM_SIGNED, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					false, // big endian?
+					properties);
+
+			supportedFormats.add(A_SAMPLE_S16LE);
+		}
+
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S32BE");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+
+			int sampleSize = 32;
+			final AudioFormat PA_SAMPLE_S32BE = new AudioFormat(
+					Encoding.PCM_SIGNED, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					true, // big endian?
+					properties);
+
+			supportedFormats.add(PA_SAMPLE_S32BE);
+		}
+
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S32LE");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+
+			int sampleSize = 32;
+			final AudioFormat PA_SAMPLE_S32LE = new AudioFormat(
+					Encoding.PCM_SIGNED, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					false, // big endian?
+					properties);
+
+			supportedFormats.add(PA_SAMPLE_S32LE);
+		}
+		
+		return supportedFormats.toArray(new AudioFormat[0]);
+	}
+	
+	
 	@Override
 	public Line getLine(javax.sound.sampled.Line.Info info)
 			throws LineUnavailableException {
@@ -100,62 +282,61 @@
 		if (!this.isOpen) {
 			throw new LineUnavailableException();
 		}
-
-		PulseAudioSourceDataLine sourceLine = null;
-		sourceLine = new PulseAudioSourceDataLine(eventLoop);
-		Line.Info sourceDataLineInfo = sourceLine.getLineInfo();
-
-		if (DataLine.class.isAssignableFrom(info.getLineClass())
-				&& info instanceof DataLine.Info) {
-			System.out
-					.println("DEBUG: trying to find data line with last matching format");
-
-			DataLine.Info dataLineInfo = (DataLine.Info) info;
-			// need to find the DataLine with the last valid format
-			AudioFormat[] wantedFormats = dataLineInfo.getFormats();
-			AudioFormat[] availableFormats = ((DataLine.Info) sourceDataLineInfo)
-					.getFormats();
-			for (int i = wantedFormats.length - 1; i > -1; i--) {
-				for (AudioFormat aFormat : availableFormats) {
-					if (wantedFormats[i].matches(aFormat)) {
-						System.out.println("DEBUG: found a matching format");
-						System.out.println("wanted: " + wantedFormats[i]);
-						System.out.println("available: " + aFormat);
-						sourceLine.setDefaultFormat(wantedFormats[i]);
-						sourceLines.add(sourceLine);
-						return sourceLine;
+		
+		if (!isLineSupported(info)) {
+	          throw new IllegalArgumentException("Line unsupported: " + info);
+		}
+	
+		AudioFormat[] formats = null;
+		AudioFormat defaultFormat = null;
+	
+		
+		if(DataLine.Info.class.isInstance(info)) {
+			ArrayList<AudioFormat> formatList = new ArrayList<AudioFormat>();
+			AudioFormat[] requestedFormats = ((DataLine.Info) info).getFormats();
+			 for (int i = 0; i< requestedFormats.length; i++) {
+				AudioFormat f1 = requestedFormats[i];
+				for (AudioFormat f2 : getSupportedFormats()){
+					
+					if(f1.matches(f2)) {
+						formatList.add(f2);
+						defaultFormat = f1;
 					}
 				}
 			}
-
-			System.out.println("DEBUG: no matches found");
-			// no format matches, so return any line
-			throw new IllegalArgumentException("No matching format found");
-
-		}
-
-		if (info.matches(sourceDataLineInfo)) {
-			sourceLines.add(sourceLine);
-			return sourceLine;
+			formats = formatList.toArray(new AudioFormat[0]);
+			
+		} else {
+			formats = getSupportedFormats();
+			defaultFormat = new AudioFormat(Encoding.PCM_UNSIGNED, 22050, 8, 2,
+					2, AudioSystem.NOT_SPECIFIED, false);
 		}
 
-		// if (info.matches(_targetDataLineInfo)) {
-		// PulseAudioTargetDataLine targetLine = new PulseAudioTargetDataLine();
-		// _targetLines.add(targetLine);
-		// return targetLine;
-		// }
 
-		PulseAudioClip clip = new PulseAudioClip();
+		if ((info.getLineClass() == SourceDataLine.class)) {
+				return new PulseAudioSourceDataLine(eventLoop, formats, defaultFormat);
+	    }
+	        
+		/*if ((info.getLineClass() == TargetDataLine.class)) {
+	          return new PulseAudioTargetDataLine(this, (DataLine.Info) info);
+	    }*/
 		
-		if (info.matches(clip.getLineInfo())) {
-			clips.add(clip);
-			return clip;
-		}
-		
-		
-		throw new IllegalArgumentException();
+		PulseAudioClip clip = new PulseAudioClip();
+
+        if (info.matches(clip.getLineInfo())) {
+                clips.add(clip);
+                return clip;
+        }
+        
+        throw new IllegalArgumentException();
+
+
+
+
+
 	}
 
+
 	@Override
 	public int getMaxLines(javax.sound.sampled.Line.Info info) {
 		return AudioSystem.NOT_SPECIFIED;
@@ -166,31 +347,24 @@
 		return PulseAudioMixerInfo.getInfo();
 	}
 
-	@Override
 	public javax.sound.sampled.Line.Info[] getSourceLineInfo() {
-		if (isOpen) {
-			SourceDataLine sourceLine = new PulseAudioSourceDataLine(eventLoop);
-			Line.Info[] info = new Line.Info[] { sourceLine.getLineInfo() };
-			return info;
-		}
-
-		// if not open, then return empty array
-		return new Line.Info[] {};
+		Line.Info[] localArray = new Line.Info[sourceLineInfos.length];
+		System.arraycopy(sourceLineInfos, 0, localArray, 0, sourceLineInfos.length);
+		return localArray;
 	}
 
 	@Override
 	public javax.sound.sampled.Line.Info[] getSourceLineInfo(
 			javax.sound.sampled.Line.Info info) {
-		Line.Info sourceInfo = new Line.Info(PulseAudioSourceDataLine.class);
-		if (info.matches(sourceInfo)) {
-			Line.Info[] sourceInfos = { sourceInfo, };
-			return sourceInfos;
-		} else {
-			Line.Info[] sourceInfos = {};
-			return sourceInfos;
+	        ArrayList<javax.sound.sampled.Line.Info> infos = new ArrayList<javax.sound.sampled.Line.Info>();
 
-		}
-	}
+	        for (Line.Info supportedInfo : sourceLineInfos) {
+	            if (info.matches(supportedInfo)) {
+	                infos.add(supportedInfo);
+	            }
+	        }
+	        return infos.toArray(new Line.Info[infos.size()]);
+	 }
 
 	@Override
 	public Line[] getSourceLines() {
@@ -201,21 +375,22 @@
 
 	@Override
 	public javax.sound.sampled.Line.Info[] getTargetLineInfo() {
-		Line.Info[] info = { new Line.Info(PulseAudioTargetDataLine.class), };
-		return info;
+		Line.Info[] localArray = new Line.Info[targetLineInfos.length];
+		System.arraycopy(targetLineInfos, 0, localArray, 0, targetLineInfos.length);
+		return localArray;
 	}
 
 	@Override
 	public javax.sound.sampled.Line.Info[] getTargetLineInfo(
 			javax.sound.sampled.Line.Info info) {
-		Line.Info sourceInfo = new Line.Info(PulseAudioTargetDataLine.class);
-		if (info.matches(sourceInfo)) {
-			Line.Info[] sourceInfos = { sourceInfo, };
-			return sourceInfos;
-		} else {
-			Line.Info[] sourceInfos = {};
-			return sourceInfos;
-		}
+	        ArrayList<javax.sound.sampled.Line.Info> infos = new ArrayList<javax.sound.sampled.Line.Info>();
+
+	        for (Line.Info supportedInfo : targetLineInfos) {
+	            if (info.matches(supportedInfo)) {
+	                infos.add(supportedInfo);
+	            }
+	        }
+	        return infos.toArray(new Line.Info[infos.size()]);
 	}
 
 	@Override
@@ -226,10 +401,21 @@
 
 	@Override
 	public boolean isLineSupported(javax.sound.sampled.Line.Info info) {
-		// if ( _sourceDataLineInfo.matches(info)) {
-		// return true;
-		// }
-		return false;
+		 if (info != null) {
+	            for (int i = 0; i < sourceLineInfos.length; i++) {
+	                if (info.matches(sourceLineInfos[i])) {
+	                    return true;
+	                }
+	            }
+	            
+	            for (int i = 0; i < targetLineInfos.length; i++) {
+	                if (info.matches(targetLineInfos[i])) {
+	                    return true;
+	                }
+	            }
+	      }
+	      return false;
+
 	}
 
 	@Override
@@ -455,46 +641,22 @@
 			}
 		}
 
-		PulseAudioMixer selectedMixer = (PulseAudioMixer) AudioSystem
+		PulseAudioMixer mixer = (PulseAudioMixer) AudioSystem
 				.getMixer(selectedMixerInfo);
 
-		selectedMixer.open();
-		SourceDataLine line = (SourceDataLine) selectedMixer
-				.getLine(new Line.Info(PulseAudioSourceDataLine.class));
-
-		System.out.println("got a line");
-
-		// File soundFile = new File(new java.io.File(".").getCanonicalPath() +
-		// "/testsounds/logout.wav");
-		File soundFile = new File(
-				"/home/iivan/workspace/pulseaudio/testsounds/logout.wav");
+		mixer.open();
+		File soundFile = new File("testsounds/startup.wav");
 		AudioInputStream audioInputStream = AudioSystem
 				.getAudioInputStream(soundFile);
 		AudioFormat audioFormat = audioInputStream.getFormat();
-		line.open(audioFormat);
-		line.start();
-		PulseAudioStreamVolumeControl control = (PulseAudioStreamVolumeControl) line
-				.getControl(FloatControl.Type.VOLUME);
-		PulseAudioStreamMuteControl mute = (PulseAudioStreamMuteControl) line
-				.getControl(BooleanControl.Type.MUTE);
-		mute.setValue(true);
-		control.setValue(40000);
-		mute.setValue(false);
-		System.out.println("Volume set to " + control.getValue());
 
-		byte[] abData = new byte[1000];
-		int bytesRead = 0;
+		SourceDataLine line;
+		line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+				SourceDataLine.class, audioFormat));
 
-		while (bytesRead >= 0) {
-			bytesRead = audioInputStream.read(abData, 0, abData.length);
-			if (bytesRead > 0) {
-				line.write(abData, 0, bytesRead);
-			}
-		}
-
-		System.out.println("about to close");
-		line.flush();
-		selectedMixer.close();
+		line.open();
+		System.out.println(line.getFormat().matches(audioFormat));
+		mixer.close();
 
 	}
 
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java	Wed Aug 13 13:17:13 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLine.java	Wed Aug 13 14:22:35 2008 -0400
@@ -69,7 +69,7 @@
 	private boolean isOpen = false;
 	private boolean isPaused = false;
 
-	private List<AudioFormat> supportedFormats = null;
+	private AudioFormat[] supportedFormats = null;
 	private AudioFormat currentFormat = null;
 	private AudioFormat defaultFormat = null;
 
@@ -112,202 +112,26 @@
 
 	static {
 		try {
-			String library = new java.io.File(".").getCanonicalPath()
-					+ java.io.File.separatorChar
+			String library = new java.io.File(".").getCanonicalPath()	+ java.io.File.separatorChar
 					+ System.mapLibraryName("pulse-java");
 			System.out.println(library);
 			System.load(library);
 		} catch (IOException e) {
 			assert ("Loading failed".endsWith("library"));
 		}
-
 	}
 
-	public PulseAudioSourceDataLine(EventLoop eventLoop) {
+	public PulseAudioSourceDataLine(EventLoop eventLoop, AudioFormat[] formats, AudioFormat defaultFormat) {
+		if (formats == null) {
+			
+		}
+		
+		supportedFormats = formats;
 		this.eventLoop = eventLoop;
 		this.lineListeners = new ArrayList<LineListener>();
 		this.volume = PulseAudioVolumeControl.MAX_VOLUME;
-
-		/*
-		 * FIXME puselaudio supports any sample rate (it can covert between
-		 * sample rates without a problem). it calculates the frame size and the
-		 * frame rate based on that.
-		 * 
-		 * Java's AudioSystem interface accepts NOT_SPECIFIED only for sample
-		 * rate and frame rate. eg: cant say that it supports any number of
-		 * audio channels
-		 * 
-		 * sample size in bytes [PA_SAMPLE_U8] = 1, [PA_SAMPLE_ULAW] = 1,
-		 * [PA_SAMPLE_ALAW] = 1, [PA_SAMPLE_S16LE] = 2, [PA_SAMPLE_S16BE] = 2,
-		 * [PA_SAMPLE_FLOAT32LE] = 4, [PA_SAMPLE_FLOAT32BE] = 4,
-		 * [PA_SAMPLE_S32LE] = 4, [PA_SAMPLE_S32BE] = 4,
-		 * 
-		 * 
-		 */
-
-		supportedFormats = new LinkedList<AudioFormat>();
-
-		Map<String, Object> properties;
-
-		int[] channelSizes = new int[] { 1, 2, 5 };
-		for (int channelSize : channelSizes) {
-			properties = new HashMap<String, Object>();
-			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_U8");
-
-			// frameSize = sample size (in bytes, not bits) x # of channels
-			// ^ that's from PulseAudio sources, so it will pretty much break
-			// as soon as they change something
-			// FIXME ^
-			int sampleSize = 8; // in bits
-			AudioFormat PA_SAMPLE_U8 = new AudioFormat(Encoding.PCM_UNSIGNED, // encoding
-					AudioSystem.NOT_SPECIFIED, // sample rate
-					sampleSize, // sample size
-					channelSize, // channels
-					sampleSize / 8 * channelSize, // frame size in bytes
-					AudioSystem.NOT_SPECIFIED, // frame rate
-					false, // big endian?
-					properties);
-
-			supportedFormats.add(PA_SAMPLE_U8);
-		}
-
-		for (int channelSize : channelSizes) {
-			properties = new HashMap<String, Object>();
-			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_ALAW");
-
-			// frameSize = sample size (in bytes, not bits) x # of channels
-			// ^ that's from PulseAudio sources, so it will pretty much break
-			// as soon as they change something
-			// FIXME ^
-
-			int sampleSize = 8;
-			final AudioFormat PA_SAMPLE_ALAW = new AudioFormat(Encoding.ALAW, // encoding
-					AudioSystem.NOT_SPECIFIED, // sample rate
-					sampleSize, // sample size
-					channelSize, // channels
-					sampleSize / 8 * channelSize, // frame size
-					AudioSystem.NOT_SPECIFIED, // frame rate
-					false, // big endian?
-					properties);
-
-			supportedFormats.add(PA_SAMPLE_ALAW);
-		}
-
-		for (int channelSize : channelSizes) {
-			properties = new HashMap<String, Object>();
-			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_ULAW");
-
-			// frameSize = sample size (in bytes, not bits) x # of channels
-			// ^ that's from PulseAudio sources, so it will pretty much break
-			// as soon as they change something
-			// FIXME ^
-
-			int sampleSize = 8;
-			final AudioFormat PA_SAMPLE_ULAW = new AudioFormat(Encoding.ULAW, // encoding
-					AudioSystem.NOT_SPECIFIED, // sample rate
-					sampleSize, // sample size
-					channelSize, // channels
-					sampleSize / 8 * channelSize, // frame size
-					AudioSystem.NOT_SPECIFIED, // frame rate
-					false, // big endian?
-					properties);
-
-			supportedFormats.add(PA_SAMPLE_ULAW);
-		}
-
-		for (int channelSize : channelSizes) {
-			properties = new HashMap<String, Object>();
-			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S16BE");
-
-			// frameSize = sample size (in bytes, not bits) x # of channels
-			// ^ that's from PulseAudio sources, so it will pretty much break
-			// as soon as they change something
-			// FIXME ^
-
-			int sampleSize = 16;
-			final AudioFormat PA_SAMPLE_S16BE = new AudioFormat(
-					Encoding.PCM_SIGNED, // encoding
-					AudioSystem.NOT_SPECIFIED, // sample rate
-					sampleSize, // sample size
-					channelSize, // channels
-					sampleSize / 8 * channelSize, // frame size
-					AudioSystem.NOT_SPECIFIED, // frame rate
-					true, // big endian?
-					properties);
-
-			supportedFormats.add(PA_SAMPLE_S16BE);
-		}
-
-		for (int channelSize : channelSizes) {
-			properties = new HashMap<String, Object>();
-			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S16LE");
-
-			// frameSize = sample size (in bytes, not bits) x # of channels
-			// ^ that's from PulseAudio sources, so it will pretty much break
-			// as soon as they change something
-			// FIXME ^
-
-			int sampleSize = 16;
-			final AudioFormat A_SAMPLE_S16LE = new AudioFormat(
-					Encoding.PCM_SIGNED, // encoding
-					AudioSystem.NOT_SPECIFIED, // sample rate
-					sampleSize, // sample size
-					channelSize, // channels
-					sampleSize / 8 * channelSize, // frame size
-					AudioSystem.NOT_SPECIFIED, // frame rate
-					false, // big endian?
-					properties);
-
-			supportedFormats.add(A_SAMPLE_S16LE);
-		}
-
-		for (int channelSize : channelSizes) {
-			properties = new HashMap<String, Object>();
-			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S32BE");
-
-			// frameSize = sample size (in bytes, not bits) x # of channels
-			// ^ that's from PulseAudio sources, so it will pretty much break
-			// as soon as they change something
-			// FIXME ^
-
-			int sampleSize = 32;
-			final AudioFormat PA_SAMPLE_S32BE = new AudioFormat(
-					Encoding.PCM_SIGNED, // encoding
-					AudioSystem.NOT_SPECIFIED, // sample rate
-					sampleSize, // sample size
-					channelSize, // channels
-					sampleSize / 8 * channelSize, // frame size
-					AudioSystem.NOT_SPECIFIED, // frame rate
-					true, // big endian?
-					properties);
-
-			supportedFormats.add(PA_SAMPLE_S32BE);
-		}
-
-		for (int channelSize : channelSizes) {
-			properties = new HashMap<String, Object>();
-			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S32LE");
-
-			// frameSize = sample size (in bytes, not bits) x # of channels
-			// ^ that's from PulseAudio sources, so it will pretty much break
-			// as soon as they change something
-			// FIXME ^
-
-			int sampleSize = 32;
-			final AudioFormat PA_SAMPLE_S32LE = new AudioFormat(
-					Encoding.PCM_SIGNED, // encoding
-					AudioSystem.NOT_SPECIFIED, // sample rate
-					sampleSize, // sample size
-					channelSize, // channels
-					sampleSize / 8 * channelSize, // frame size
-					AudioSystem.NOT_SPECIFIED, // frame rate
-					false, // big endian?
-					properties);
-
-			supportedFormats.add(PA_SAMPLE_S32LE);
-		}
-
-		currentFormat = null;
+		this.defaultFormat = defaultFormat; 
+		this.currentFormat = defaultFormat;
 
 	}
 
@@ -622,8 +446,9 @@
 	}
 
 	public javax.sound.sampled.Line.Info getLineInfo() {
-		return new DataLine.Info(SourceDataLine.class, supportedFormats
-				.toArray(new AudioFormat[0]), 0, 100000);
+		/*return new DataLine.Info(SourceDataLine.class, supportedFormats
+				.toArray(new AudioFormat[0]), 0, 100000);*/
+		return null;
 	}
 
 	public boolean isControlSupported(Type control) {
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.java	Wed Aug 13 13:17:13 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioStreamVolumeControl.java	Wed Aug 13 14:22:35 2008 -0400
@@ -17,8 +17,10 @@
 	static {
 		try {
 			String library = new java.io.File(".").getCanonicalPath()
+
 					+ java.io.File.separatorChar
 					+ System.mapLibraryName("pulse-java");
+
 			System.out.println(library);
 			System.load(library);
 		} catch (IOException e) {
--- a/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java	Wed Aug 13 13:17:13 2008 -0400
+++ b/src/java/org/classpath/icedtea/pulseaudio/PulseAudioTargetDataLine.java	Wed Aug 13 14:22:35 2008 -0400
@@ -39,18 +39,32 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
 import javax.sound.sampled.*;
+import javax.sound.sampled.AudioFormat.Encoding;
 import javax.sound.sampled.Control.Type;
 
 public class PulseAudioTargetDataLine implements TargetDataLine {
 
+	
 	protected long contextPointer;
 	protected long mainLoopPointer;
 	protected long streamPointer;
 	protected boolean isOpen = false;
 	protected boolean isPaused = false;
 	protected int defaultBufferSize;
+	
+	
+	private static final int DEFAULT_BUFFER_SIZE = 1000;
+	private static final String PULSEAUDIO_FORMAT_KEY = "PulseAudioFormatKey";
+	private List<AudioFormat> supportedFormats = null;
+	private AudioFormat currentFormat = null;
+	private EventLoop eventLoop = null;
+	
 	protected ArrayList<LineListener> listeners;
 
 	static {
@@ -65,6 +79,198 @@
 			assert ("Loading failed".endsWith("library"));
 		}
 	}
+	
+	public PulseAudioTargetDataLine(EventLoop eventLoop) {
+		this.eventLoop = eventLoop;
+		this.listeners = new ArrayList<LineListener>();
+	
+
+
+
+		/*
+		 * FIXME puselaudio supports any sample rate (it can covert between
+		 * sample rates without a problem). it calculates the frame size and the
+		 * frame rate based on that.
+		 * 
+		 * Java's AudioSystem interface accepts NOT_SPECIFIED only for sample
+		 * rate and frame rate. eg: cant say that it supports any number of
+		 * audio channels
+		 * 
+		 * sample size in bytes [PA_SAMPLE_U8] = 1, [PA_SAMPLE_ULAW] = 1,
+		 * [PA_SAMPLE_ALAW] = 1, [PA_SAMPLE_S16LE] = 2, [PA_SAMPLE_S16BE] = 2,
+		 * [PA_SAMPLE_FLOAT32LE] = 4, [PA_SAMPLE_FLOAT32BE] = 4,
+		 * [PA_SAMPLE_S32LE] = 4, [PA_SAMPLE_S32BE] = 4,
+		 * 
+		 * 
+		 */
+		
+		supportedFormats = new LinkedList<AudioFormat>();
+		
+		Map<String, Object> properties;
+
+		int[] channelSizes = new int[] { 1, 2, 5 };
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_U8");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+			int sampleSize = 8; // in bits
+			AudioFormat PA_SAMPLE_U8 = new AudioFormat(
+					Encoding.PCM_UNSIGNED, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size in bytes
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					false, // big endian?
+					properties);
+
+			supportedFormats.add(PA_SAMPLE_U8);
+		}
+
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_ALAW");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+
+			int sampleSize = 8;
+			final AudioFormat PA_SAMPLE_ALAW = new AudioFormat(Encoding.ALAW, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					false, // big endian?
+					properties);
+
+			supportedFormats.add(PA_SAMPLE_ALAW);
+		}
+
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_ULAW");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+
+			int sampleSize = 8;
+			final AudioFormat PA_SAMPLE_ULAW = new AudioFormat(Encoding.ULAW, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					false, // big endian?
+					properties);
+
+			supportedFormats.add(PA_SAMPLE_ULAW);
+		}
+
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S16BE");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+
+			int sampleSize = 16;
+			final AudioFormat PA_SAMPLE_S16BE = new AudioFormat(
+					Encoding.PCM_SIGNED, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					true, // big endian?
+					properties);
+
+			supportedFormats.add(PA_SAMPLE_S16BE);
+		}
+
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S16LE");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+
+			int sampleSize = 16;
+			final AudioFormat A_SAMPLE_S16LE = new AudioFormat(
+					Encoding.PCM_SIGNED, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					false, // big endian?
+					properties);
+
+			supportedFormats.add(A_SAMPLE_S16LE);
+		}
+
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S32BE");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+
+			int sampleSize = 32;
+			final AudioFormat PA_SAMPLE_S32BE = new AudioFormat(
+					Encoding.PCM_SIGNED, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					true, // big endian?
+					properties);
+
+			supportedFormats.add(PA_SAMPLE_S32BE);
+		}
+
+		for (int channelSize : channelSizes) {
+			properties = new HashMap<String, Object>();
+			properties.put(PULSEAUDIO_FORMAT_KEY, "PA_SAMPLE_S32LE");
+
+			// frameSize = sample size (in bytes, not bits) x # of channels
+			// ^ that's from PulseAudio sources, so it will pretty much break
+			// as soon as they change something
+			// FIXME ^
+
+			int sampleSize = 32;
+			final AudioFormat PA_SAMPLE_S32LE = new AudioFormat(
+					Encoding.PCM_SIGNED, // encoding
+					AudioSystem.NOT_SPECIFIED, // sample rate
+					sampleSize, // sample size
+					channelSize, // channels
+					sampleSize / 8 * channelSize, // frame size
+					AudioSystem.NOT_SPECIFIED, // frame rate
+					false, // big endian?
+					properties);
+
+			supportedFormats.add(PA_SAMPLE_S32LE);
+		}
+
+		currentFormat = null;
+
+
+	}
 
 	public void open(AudioFormat format, int bufferSize)
 			throws LineUnavailableException {
--- a/src/native/org_classpath_icedtea_pulseaudio_Operation.c	Wed Aug 13 13:17:13 2008 -0400
+++ b/src/native/org_classpath_icedtea_pulseaudio_Operation.c	Wed Aug 13 14:22:35 2008 -0400
@@ -72,7 +72,7 @@
  * Signature: ()I
  */
 JNIEXPORT jint JNICALL Java_org_classpath_icedtea_pulseaudio_Operation_native_1get_1state
-(JNIEnv* env, jobject obj) {
+(JNIEnv *env, jobject obj) {
 
 	pa_operation* operation = (pa_operation*) getJavaPointer(env, obj, "operationPointer");
 	int state = pa_operation_get_state(operation);