changeset 27:f1a1eaa0f610

merging part 2 committer: Omair Majid <omajid@redhat.com>
author Omair Majid <omajid@redhat.com>
date Thu, 31 Jul 2008 17:29:47 -0400
parents bc8045fdeaf2
children dbffaa5c4944 b9836224602b
files makefile src/org/openjdk/sound/PulseAudioMixer.java src/org/openjdk/sound/PulseAudioSourceDataLine.java src/org_openjdk_sound_PulseAudioSourceDataLine.c src/org_openjdk_sound_PulseAudioSourceDataLine.c_ORIGINAL src/org_openjdk_sound_PulseAudioSourceDataLine.h
diffstat 6 files changed, 489 insertions(+), 307 deletions(-) [+]
line wrap: on
line diff
--- a/makefile	Thu Jul 31 16:39:41 2008 -0400
+++ b/makefile	Thu Jul 31 17:29:47 2008 -0400
@@ -21,8 +21,8 @@
 # Shared Libraries
 
 lib/libpulse-java.so: \
-                      bin/org_openjdk_sound_EventLoop.o 
-#                      bin/org_openjdk_sound_PulseAudioSourceDataLine.o \
+                      bin/org_openjdk_sound_EventLoop.o \
+                      bin/org_openjdk_sound_PulseAudioSourceDataLine.o 
 #                      bin/org_openjdk_sound_PulseAudioTargetDataLine.o 
 	gcc -g -shared -o $@ $^ /usr/lib/libpulse.so
 
@@ -31,8 +31,8 @@
 bin/org_openjdk_sound_EventLoop.o: src/org_openjdk_sound_EventLoop.c src/org_openjdk_sound_EventLoop.h bin
 	gcc -g -c -o $@ $<
 
-#bin/org_openjdk_sound_PulseAudioSourceDataLine.o: src/org_openjdk_sound_PulseAudioSourceDataLine.c src/org_openjdk_sound_PulseAudioSourceDataLine.h bin
-#	gcc -g -c -o $@ $<
+bin/org_openjdk_sound_PulseAudioSourceDataLine.o: src/org_openjdk_sound_PulseAudioSourceDataLine.c src/org_openjdk_sound_PulseAudioSourceDataLine.h bin
+	gcc -g -c -o $@ $<
 
 #bin/org_openjdk_sound_PulseAudioTargetDataLine.o: src/org_openjdk_sound_PulseAudioTargetDataLine.c src/org_openjdk_sound_PulseAudioTargetDataLine.h bin
 #	gcc -g -c -o $@ $<
@@ -42,8 +42,8 @@
 src/org_openjdk_sound_EventLoop.h: src/org/openjdk/sound/EventLoop.class
 	javah -d src -classpath src org.openjdk.sound.EventLoop
 
-#src/org_openjdk_sound_PulseAudioSourceDataLine.h: src/org/openjdk/sound/PulseAudioSourceDataLine.class
-#	javah -d src -classpath src org.openjdk.sound.PulseAudioSourceDataLine
+src/org_openjdk_sound_PulseAudioSourceDataLine.h: src/org/openjdk/sound/PulseAudioSourceDataLine.class
+	javah -d src -classpath src org.openjdk.sound.PulseAudioSourceDataLine
 
 #src/org_openjdk_sound_PulseAudioTargetDataLine.h: src/org/openjdk/sound/PulseAudioTargetDataLine.class
 #	javah -d src -classpath src org.openjdk.sound.PulseAudioTargetDataLine
@@ -53,14 +53,15 @@
 src/org/openjdk/sound/EventLoop.class: src/org/openjdk/sound/EventLoop.java
 	javac -classpath src $<
 
-#src/org/openjdk/sound/PulseAudioSourceDataLine.class: src/org/openjdk/sound/PulseAudioSourceDataLine.java 
-#	javac $<
-#
+src/org/openjdk/sound/PulseAudioSourceDataLine.class: src/org/openjdk/sound/PulseAudioSourceDataLine.java 
+	javac -classpath src $<
+
 #src/org/openjdk/sound/PulseAudioTargetDataLine.class: src/org/openjdk/sound/PulseAudioTargetDataLine.java 
 #	javac $<
 #
-#src/org/openjdk/sound/PulseAudioMixerInfo.class: src/org/openjdk/sound/PulseAudioMixerInfo.java 
-#	javac $<
+
+src/org/openjdk/sound/PulseAudioMixerInfo.class: src/org/openjdk/sound/PulseAudioMixerInfo.java 
+	javac $<
 	
 # Build Directories	
 	
--- a/src/org/openjdk/sound/PulseAudioMixer.java	Thu Jul 31 16:39:41 2008 -0400
+++ b/src/org/openjdk/sound/PulseAudioMixer.java	Thu Jul 31 17:29:47 2008 -0400
@@ -23,9 +23,9 @@
 
 	private static PulseAudioMixer _instance = null;
 
-	private final String DEFAULT_APP_NAME = "Java App";
+	private static final String DEFAULT_APP_NAME = "Java App";
 
-	private boolean _isOpen = false;
+	private boolean isOpen = false;
 
 	// private List<PulseAudioSourceDataLine> _sourceLines = null;
 	// private List<PulseAudioTargetDataLine> _targetLines = null;
@@ -54,7 +54,7 @@
 	public Line getLine(javax.sound.sampled.Line.Info info)
 			throws LineUnavailableException {
 
-		if (!_isOpen) {
+		if (!this.isOpen) {
 			throw new LineUnavailableException();
 		}
 
@@ -171,7 +171,7 @@
 	@Override
 	synchronized public void close() {
 
-		if (!_isOpen) {
+		if (!this.isOpen) {
 			return; // TODO do we throw an exception too?
 		}
 
@@ -186,7 +186,7 @@
 
 		System.out.println(this.getClass().getName() + ": closing");
 
-		_isOpen = false;
+		this.isOpen = false;
 		fireEvent(new LineEvent(this, LineEvent.Type.CLOSE,
 				AudioSystem.NOT_SPECIFIED));
 
@@ -221,7 +221,7 @@
 
 	@Override
 	public boolean isOpen() {
-		return _isOpen;
+		return this.isOpen;
 	}
 
 	@Override
@@ -253,7 +253,7 @@
 
 	synchronized public void openRemote(String appName, String host,
 			Integer port) throws UnknownHostException, LineUnavailableException {
-		if (_isOpen) {
+		if (this.isOpen) {
 			return;
 		}
 
@@ -301,7 +301,7 @@
 			System.out.println("got interrupted");
 		}
 
-		_isOpen = true;
+		this.isOpen = true;
 		fireEvent(new LineEvent(this, LineEvent.Type.OPEN,
 				AudioSystem.NOT_SPECIFIED));
 
--- a/src/org/openjdk/sound/PulseAudioSourceDataLine.java	Thu Jul 31 16:39:41 2008 -0400
+++ b/src/org/openjdk/sound/PulseAudioSourceDataLine.java	Thu Jul 31 17:29:47 2008 -0400
@@ -3,19 +3,55 @@
 import java.io.IOException;
 import java.util.ArrayList;
 
-import javax.sound.sampled.*;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.Control;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineEvent;
+import javax.sound.sampled.LineListener;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.AudioFormat.Encoding;
 import javax.sound.sampled.Control.Type;
 
 public class PulseAudioSourceDataLine implements SourceDataLine {
 
+	
+	
+	private static final int DEFAULT_BUFFER_SIZE = 1000;
+	private String streamName = "Java Stream";
+	
 	private EventLoop eventLoop = null;
-	private int streamPointer;
 
 	private boolean isOpen = false;
 	private boolean isPaused = false;
-	private int defaultBufferSize;
+
+	private final AudioFormat format = null;
+	
 	private ArrayList<LineListener> listeners;
 
+	@SuppressWarnings("unused")
+	private int streamPointer;
+
+	private native void native_open(int contextPointer, String name, String encoding, float rate, int size,
+			int channels, boolean bigEndian, int bufferSize);
+
+	private native void native_write(byte[] data, int offset, int length);
+
+	private native int native_get_writable_size();
+
+	private native void native_flush();
+	
+	private native void native_start();
+	
+	private native void native_pause();
+
+	private native void native_resume();
+	
+	private native void native_drain();
+
+	private native void native_close();
+
+
 	static {
 		try {
 			String library = new java.io.File(".").getCanonicalPath()
@@ -42,39 +78,52 @@
 		int sampleSize = format.getSampleSizeInBits();
 		String encoding = format.getEncoding().toString();
 		boolean bigEndian = format.isBigEndian();
-		openStream(encoding, rate, sampleSize, channels, bigEndian, bufferSize);
+		
+		synchronized (eventLoop.threadLock) {
+			native_open(eventLoop.getContextPointer(), streamName, encoding, rate, sampleSize, channels, bigEndian, bufferSize);
+		}
 	}
 
 	public void open(AudioFormat format) throws LineUnavailableException {
-		open(format, defaultBufferSize);
+		open(format, DEFAULT_BUFFER_SIZE);
 
 	}
 
 	public void open() throws LineUnavailableException {
-		synchronized (eventLoop.threadLock) {
-			openStream("PCM_SIGNED", 44100, 16, 2, false, defaultBufferSize);
-
-		}
+//		format = new AudioFormat(Encoding.PCM_SIGNED, 44100, 16, 2, );
+		
+//		synchronized (eventLoop.threadLock) {
+//			openStream("PCM_SIGNED", 44100, 16, 2, false, DEFAULT_BUFFER_SIZE);
+//
+//		}
+		
+		open(null);
+		
 	}
 
-	private native void openStream(String encoding, float rate, int size,
-			int channels, boolean bigEndian, int bufferSize);
+	public int write(byte[] data, int off, int len) {
+		// FIXME
+		
+		
+		synchronized (eventLoop.threadLock) {
+			native_write(data, off, len);
+		}
 
-	public int write(byte[] b, int off, int len) {
-		writeToStream(b, len, off);
+		/*
+		 * FIXME when the stream is flushed() etc, instead of returning length
+		 * this should unblock and return the the size of data written so far
+		 */
 		return len;
 	}
 
-	private native void writeToStream(byte[] data, int bytes, int off);
-
 	public void start() {
 		if (isPaused) {
-			resumeStream();
+			native_resume();
 			isPaused = false;
 		} else {
-			startStream();
+			native_start();
 		}
-		
+
 		/*
 		 * for(LineListener l :listeners) { l.update(new LineEvent(this,
 		 * LineEvent.Type.START, 0)); }
@@ -82,21 +131,13 @@
 	}
 
 	public void stop() {
-		pauseStream();
+		synchronized (eventLoop.threadLock) {
+			native_pause();
+		}
 		isPaused = true;
 
 	}
 
-	private native void startStream();
-
-	private native void pauseStream();
-
-	private native void resumeStream();
-
-	public native void drain();
-
-	public native void flush();
-
 	public void addLineListener(LineListener listener) {
 		this.listeners.add(listener);
 	}
@@ -112,14 +153,17 @@
 	public native int available();
 
 	public void close() {
-		closeStream();
+		synchronized (eventLoop.threadLock) {
+			native_close();
+		}
+		
+		
 		for (LineListener l : this.listeners) {
 			l.update(new LineEvent(this, LineEvent.Type.CLOSE, 0));
 		}
 
 	}
 
-	private native void closeStream();
 
 	public int getBufferSize() {
 		// TODO Auto-generated method stub
@@ -180,4 +224,16 @@
 		return false;
 	}
 
+	@Override
+	public void drain() {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void flush() {
+		// TODO Auto-generated method stub
+
+	}
+
 }
--- a/src/org_openjdk_sound_PulseAudioSourceDataLine.c	Thu Jul 31 16:39:41 2008 -0400
+++ b/src/org_openjdk_sound_PulseAudioSourceDataLine.c	Thu Jul 31 17:29:47 2008 -0400
@@ -1,260 +1,115 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <jni.h>
-#include <pulse/pulseaudio.h>
 #include "org_openjdk_sound_PulseAudioSourceDataLine.h"
 
-void setJavaLongField(JNIEnv *env, jobject obj, void *ptr, char *fieldName) {
-	jclass cls = (*env)->GetObjectClass(env, obj);
-	jlong value = (long) ptr;
-	jfieldID fid =(*env)->GetFieldID(env, cls, fieldName, "J");
-	(*env)->SetLongField(env, obj, fid, value);
-	//CHECK No DeleteLocalReference Method?
-	//(*env)->DeleteLocalReference(cls);
-}
+#include <pulse/pulseaudio.h>
 
-void *getJavaLongField(JNIEnv *env, jobject obj, char *fieldName) {
-jclass cls = (*env)->GetObjectClass(env, obj);
-	jfieldID fid = (*env)->GetFieldID(env, cls, fieldName, "J");
-	jlong value = (*env)->GetLongField(env, obj, fid);
-	//(*env)->DeleteLocalReference(cls);
-	return (void *) value;
-}
-
+/*
+ * Class:     org_openjdk_sound_PulseAudioSourceDataLine
+ * Method:    native_open
+ * Signature: (ILjava/lang/String;Ljava/lang/String;FIIZI)V
+ */
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1open
+(JNIEnv* env, jobject obj, jint arg, jstring arg1, jstring arg2, jfloat arg3, jint arg4, jint arg5, jboolean arg6, jint arg7) {
 
-
-static void stream_write_cb(pa_stream* stream, size_t length, void* userdata) {
-    pa_threaded_mainloop *mainloop = userdata;
-    pa_threaded_mainloop_signal(mainloop,0);
-}
-
-static void stream_operation_complete_cb(pa_stream* stream, int success, void* userdata) {
-  pa_threaded_mainloop *mainloop = userdata;
-   pa_threaded_mainloop_signal(mainloop,0);
 }
 
-
-
-static void stream_state_cb(pa_stream* stream, void* userdata) {
-    assert(stream);
-    pa_threaded_mainloop *mainloop = userdata;
-    printf("stream state changed to %d\n", pa_stream_get_state(stream));
-    switch (pa_stream_get_state(stream)) {
-        case PA_STREAM_READY:
-        case PA_STREAM_FAILED:
-        pa_threaded_mainloop_signal(mainloop, 0);
-            break;
-        case PA_STREAM_TERMINATED:
-            printf("STREAM DISCONNECTING\n");
-            pa_threaded_mainloop_signal(mainloop, 0);
-            break;
-
-        default:
-            /* do nothing */
-            break;
-    }
- }
-
-
-
-
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_openStream
-  (JNIEnv * env, jobject obj, jstring string, jfloat rate, jint size, jint channels, jboolean bigEndian, jint bufferSize){
-  
-    //TO DO: Need to deal with the buffer size. Currently ignored
+/*
+ * Class:     org_openjdk_sound_PulseAudioSourceDataLine
+ * Method:    native_write
+ * Signature: ([BII)V
+ */
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1write
+(JNIEnv* env, jobject obj, jbyteArray arr, jint int1, jint int2) {
 
-    pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); 
-    pa_context *context = getJavaLongField(env, obj, "contextPointer");
-    
-   
-    pa_sample_spec sample_spec;
-    
-    char *encoding = (*env)->GetStringUTFChars(env, string, NULL);
-    
-    if( (strcmp(encoding, "PCM_UNSIGNED") == 0) && (size == 8)) {
-    	sample_spec.format = PA_SAMPLE_U8;
-    } else if( (strcmp(encoding, "ALAW") == 0) && (size == 8)) {
-    	sample_spec.format = PA_SAMPLE_ALAW;
-    } else if( (strcmp(encoding, "ULAW") == 0) && (size == 8)) {
-    	sample_spec.format = PA_SAMPLE_ULAW;
-    } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 16) && (bigEndian == 1)) {
-	sample_spec.format = PA_SAMPLE_S16BE;
-     } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 16) && (bigEndian == 0)) {
-	sample_spec.format = PA_SAMPLE_S16LE;
-     } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 32) && (bigEndian == 1)) {
-	sample_spec.format = PA_SAMPLE_S32BE;
-     } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 32) && (bigEndian == 0)) {
-	sample_spec.format = PA_SAMPLE_S32LE;
-     } else {
-     	printf("error in open");
-     	//TO DO: Invalid format :throw Exception;
-     }
-    
-    sample_spec.rate = rate;
-    sample_spec.channels = channels;
-
-    pa_threaded_mainloop_lock(mainloop);
-    
-    pa_stream *stream = pa_stream_new(context, "default stream", &sample_spec, NULL);
-
-    pa_stream_set_state_callback(stream, stream_state_cb, mainloop);
-    pa_stream_set_write_callback(stream, stream_write_cb, mainloop);
-    
-  
-    pa_threaded_mainloop_unlock(mainloop);
-
-
-    setJavaLongField(env, obj, stream, "streamPointer");    
-    return;
-
-unlock_and_fail:
-    pa_threaded_mainloop_unlock(mainloop);
-
-fail:
-    return;
+//	pa_stream* stream = (pa_stream*) streamPointer;
+//	jbyte* data_buffer = (*env)->GetByteArrayElements(env, data, NULL);
+//
+//	pa_stream_write(stream, data_buffer, data_length, NULL, 0, PA_SEEK_RELATIVE);
+//	(*env)->ReleaseByteArrayElements(env, data, data_buffer, 0);
+	
 }
 
-JNIEXPORT void JNICALL
-Java_org_openjdk_sound_PulseAudioSourceDataLine_startStream(JNIEnv *env, jobject obj) {
-    printf("start called\n");
-    pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); 
-    pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
-    pa_threaded_mainloop_lock(mainloop);
-    pa_stream_connect_playback(stream, NULL, NULL, 0, NULL, NULL);
-    pa_threaded_mainloop_wait(mainloop);
-    if ( pa_stream_get_state(stream) != PA_STREAM_READY ) {
-        printf("stream initialization failed\n");
-    }
-    pa_threaded_mainloop_unlock(mainloop);
+/*
+ * Class:     org_openjdk_sound_PulseAudioSourceDataLine
+ * Method:    native_get_writable_size
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1get_1writable_1size
+(JNIEnv* env, jobject obj) {
+	
+//	jfieldID fid = (*env)->GetIntField
+//	
+//	pa_stream* stream = (pa_stream*)streamPointer;
+//	return pa_stream_writable_size(stream);
+	
 }
 
-JNIEXPORT void Java_org_openjdk_sound_PulseAudioSourceDataLine_resumeStream(JNIEnv *env, jobject obj) {
-  	 pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); 
-  	 pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
-  	 pa_threaded_mainloop_lock(mainloop);
-    	 pa_operation *o = pa_stream_cork(stream, 0, stream_operation_complete_cb, mainloop);
-    	 while(pa_operation_get_state(o) != PA_OPERATION_DONE) {
-    		pa_threaded_mainloop_wait(mainloop);
-    	 }
-    	 pa_operation_unref(o);
-    	 pa_threaded_mainloop_unlock(mainloop);
+/*
+ * Class:     org_openjdk_sound_PulseAudioSourceDataLine
+ * Method:    native_flush
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1flush
+(JNIEnv* env, jobject obj) {
 
 }
 
-JNIEXPORT void Java_org_openjdk_sound_PulseAudioSourceDataLine__pauseStream(JNIEnv *env, jobject obj) {
-	 pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); 
-  	 pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
-  	 pa_threaded_mainloop_lock(mainloop);
-    	 pa_operation *o = pa_stream_cork(stream, 1, stream_operation_complete_cb, mainloop);
-    	 while(pa_operation_get_state(o) != PA_OPERATION_DONE) {
-    		pa_threaded_mainloop_wait(mainloop);
-    	 }
-    	 pa_operation_unref(o);
-    	 pa_threaded_mainloop_unlock(mainloop);
-}
-  
-
+/*
+ * Class:     org_openjdk_sound_PulseAudioSourceDataLine
+ * Method:    native_start
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1start
+(JNIEnv *env, jobject obj) {
 
-JNIEXPORT void JNICALL
-Java_org_openjdk_sound_PulseAudioSourceDataLine_writeToStream(JNIEnv *env, jobject obj, jbyteArray data, jint bytesRead, jint indexJava) {
-    printf("write called\n");
-    pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); 
-    pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
-    unsigned char *buffer = (*env)->GetByteArrayElements(env, data, NULL);
-    int length = bytesRead;
-    int offset = indexJava;
-    buffer += offset;
-
-
-    pa_threaded_mainloop_lock(mainloop);
-  
-    while (length > 0) {
+}
 
-	int available_size = pa_stream_writable_size(stream);
-        while (available_size == 0) {
-            pa_threaded_mainloop_wait(mainloop);
-            available_size = pa_stream_writable_size(stream);
-        }
-
-        if (available_size > length) {
-            available_size = length;
-        }
-
-        if (pa_stream_get_state(stream) != PA_STREAM_READY ) {
-            printf("stream errored!\n");
-            goto unlock_and_fail;
-        }
+/*
+ * Class:     org_openjdk_sound_PulseAudioSourceDataLine
+ * Method:    native_pause
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1pause
+(JNIEnv* env, jobject obj) {
 
-        pa_stream_write(stream, buffer, available_size, NULL, 0, PA_SEEK_RELATIVE);
-        printf("written%d\n", available_size);
-      
-
-        buffer += available_size;
-        length -= available_size;
-       
-    }
+}
 
-    pa_operation_unref(pa_stream_drain(stream, NULL, NULL));
-
-    pa_threaded_mainloop_unlock(mainloop);
-
-   
-    return;
-
-unlock_and_fail:
-    pa_threaded_mainloop_unlock(mainloop);
-fail:
-    return;
+/*
+ * Class:     org_openjdk_sound_PulseAudioSourceDataLine
+ * Method:    native_resume
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1resume
+(JNIEnv* env, jobject obj) {
 
 }
 
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_closeStream
-  (JNIEnv *env, jobject obj) {
-	pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
-	printf("STREAM POINTER: %d\n", stream);
-  	pa_stream_disconnect(stream);
+/*
+ * Class:     org_openjdk_sound_PulseAudioSourceDataLine
+ * Method:    native_drain
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1drain
+(JNIEnv* env, jobject obj) {
+
 }
 
-JNIEXPORT jint JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_available
-  (JNIEnv *env, jobject obj) {
-  	pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer");
-  	pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
-  	pa_threaded_mainloop_lock(mainloop);
-	int available = pa_stream_writable_size(stream);
-    	pa_threaded_mainloop_unlock(mainloop);
-    	return available;
- }
+/*
+ * Class:     org_openjdk_sound_PulseAudioSourceDataLine
+ * Method:    native_close
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1close
+(JNIEnv* env, jobject obj) {
 
+}
 
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_drain
-  (JNIEnv *env, jobject obj) {
-  	pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer");
-  	pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
-  	pa_threaded_mainloop_lock(mainloop);
-	pa_operation *o = pa_stream_drain(stream, stream_operation_complete_cb, mainloop);
-    	while(pa_operation_get_state(o) != PA_OPERATION_DONE) {
-    		pa_threaded_mainloop_wait(mainloop);
-    	}
-    	pa_operation_unref(o);
-    	pa_threaded_mainloop_unlock(mainloop);
- }
+/*
+ * Class:     org_openjdk_sound_PulseAudioSourceDataLine
+ * Method:    available
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_available
+(JNIEnv* env, jobject obj) {
 
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_flush
-  (JNIEnv *env, jobject obj) {
-  	pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer");
-  	pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
-  	pa_threaded_mainloop_lock(mainloop);
-	pa_operation *o = pa_stream_flush(stream, stream_operation_complete_cb, mainloop);
-    	while(pa_operation_get_state(o) != PA_OPERATION_DONE) {
-    		pa_threaded_mainloop_wait(mainloop);
-    	}
-    	pa_operation_unref(o);
-    	pa_threaded_mainloop_unlock(mainloop);
- }
+}
 
-
-
-
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org_openjdk_sound_PulseAudioSourceDataLine.c_ORIGINAL	Thu Jul 31 17:29:47 2008 -0400
@@ -0,0 +1,260 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <jni.h>
+#include <pulse/pulseaudio.h>
+#include "org_openjdk_sound_PulseAudioSourceDataLine.h"
+
+void setJavaLongField(JNIEnv *env, jobject obj, void *ptr, char *fieldName) {
+	jclass cls = (*env)->GetObjectClass(env, obj);
+	jlong value = (long) ptr;
+	jfieldID fid =(*env)->GetFieldID(env, cls, fieldName, "J");
+	(*env)->SetLongField(env, obj, fid, value);
+	//CHECK No DeleteLocalReference Method?
+	//(*env)->DeleteLocalReference(cls);
+}
+
+void *getJavaLongField(JNIEnv *env, jobject obj, char *fieldName) {
+jclass cls = (*env)->GetObjectClass(env, obj);
+	jfieldID fid = (*env)->GetFieldID(env, cls, fieldName, "J");
+	jlong value = (*env)->GetLongField(env, obj, fid);
+	//(*env)->DeleteLocalReference(cls);
+	return (void *) value;
+}
+
+
+
+static void stream_write_cb(pa_stream* stream, size_t length, void* userdata) {
+    pa_threaded_mainloop *mainloop = userdata;
+    pa_threaded_mainloop_signal(mainloop,0);
+}
+
+static void stream_operation_complete_cb(pa_stream* stream, int success, void* userdata) {
+  pa_threaded_mainloop *mainloop = userdata;
+   pa_threaded_mainloop_signal(mainloop,0);
+}
+
+
+
+static void stream_state_cb(pa_stream* stream, void* userdata) {
+    assert(stream);
+    pa_threaded_mainloop *mainloop = userdata;
+    printf("stream state changed to %d\n", pa_stream_get_state(stream));
+    switch (pa_stream_get_state(stream)) {
+        case PA_STREAM_READY:
+        case PA_STREAM_FAILED:
+        pa_threaded_mainloop_signal(mainloop, 0);
+            break;
+        case PA_STREAM_TERMINATED:
+            printf("STREAM DISCONNECTING\n");
+            pa_threaded_mainloop_signal(mainloop, 0);
+            break;
+
+        default:
+            /* do nothing */
+            break;
+    }
+ }
+
+
+
+
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_openStream
+  (JNIEnv * env, jobject obj, jstring string, jfloat rate, jint size, jint channels, jboolean bigEndian, jint bufferSize){
+  
+    //TO DO: Need to deal with the buffer size. Currently ignored
+
+    pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); 
+    pa_context *context = getJavaLongField(env, obj, "contextPointer");
+    
+   
+    pa_sample_spec sample_spec;
+    
+    char *encoding = (*env)->GetStringUTFChars(env, string, NULL);
+    
+    if( (strcmp(encoding, "PCM_UNSIGNED") == 0) && (size == 8)) {
+    	sample_spec.format = PA_SAMPLE_U8;
+    } else if( (strcmp(encoding, "ALAW") == 0) && (size == 8)) {
+    	sample_spec.format = PA_SAMPLE_ALAW;
+    } else if( (strcmp(encoding, "ULAW") == 0) && (size == 8)) {
+    	sample_spec.format = PA_SAMPLE_ULAW;
+    } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 16) && (bigEndian == 1)) {
+	sample_spec.format = PA_SAMPLE_S16BE;
+     } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 16) && (bigEndian == 0)) {
+	sample_spec.format = PA_SAMPLE_S16LE;
+     } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 32) && (bigEndian == 1)) {
+	sample_spec.format = PA_SAMPLE_S32BE;
+     } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 32) && (bigEndian == 0)) {
+	sample_spec.format = PA_SAMPLE_S32LE;
+     } else {
+     	printf("error in open");
+     	//TO DO: Invalid format :throw Exception;
+     }
+    
+    sample_spec.rate = rate;
+    sample_spec.channels = channels;
+
+    pa_threaded_mainloop_lock(mainloop);
+    
+    pa_stream *stream = pa_stream_new(context, "default stream", &sample_spec, NULL);
+
+    pa_stream_set_state_callback(stream, stream_state_cb, mainloop);
+    pa_stream_set_write_callback(stream, stream_write_cb, mainloop);
+    
+  
+    pa_threaded_mainloop_unlock(mainloop);
+
+
+    setJavaLongField(env, obj, stream, "streamPointer");    
+    return;
+
+unlock_and_fail:
+    pa_threaded_mainloop_unlock(mainloop);
+
+fail:
+    return;
+}
+
+JNIEXPORT void JNICALL
+Java_org_openjdk_sound_PulseAudioSourceDataLine_startStream(JNIEnv *env, jobject obj) {
+    printf("start called\n");
+    pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); 
+    pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
+    pa_threaded_mainloop_lock(mainloop);
+    pa_stream_connect_playback(stream, NULL, NULL, 0, NULL, NULL);
+    pa_threaded_mainloop_wait(mainloop);
+    if ( pa_stream_get_state(stream) != PA_STREAM_READY ) {
+        printf("stream initialization failed\n");
+    }
+    pa_threaded_mainloop_unlock(mainloop);
+}
+
+JNIEXPORT void Java_org_openjdk_sound_PulseAudioSourceDataLine_resumeStream(JNIEnv *env, jobject obj) {
+  	 pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); 
+  	 pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
+  	 pa_threaded_mainloop_lock(mainloop);
+    	 pa_operation *o = pa_stream_cork(stream, 0, stream_operation_complete_cb, mainloop);
+    	 while(pa_operation_get_state(o) != PA_OPERATION_DONE) {
+    		pa_threaded_mainloop_wait(mainloop);
+    	 }
+    	 pa_operation_unref(o);
+    	 pa_threaded_mainloop_unlock(mainloop);
+
+}
+
+JNIEXPORT void Java_org_openjdk_sound_PulseAudioSourceDataLine__pauseStream(JNIEnv *env, jobject obj) {
+	 pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); 
+  	 pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
+  	 pa_threaded_mainloop_lock(mainloop);
+    	 pa_operation *o = pa_stream_cork(stream, 1, stream_operation_complete_cb, mainloop);
+    	 while(pa_operation_get_state(o) != PA_OPERATION_DONE) {
+    		pa_threaded_mainloop_wait(mainloop);
+    	 }
+    	 pa_operation_unref(o);
+    	 pa_threaded_mainloop_unlock(mainloop);
+}
+  
+
+
+JNIEXPORT void JNICALL
+Java_org_openjdk_sound_PulseAudioSourceDataLine_writeToStream(JNIEnv *env, jobject obj, jbyteArray data, jint bytesRead, jint indexJava) {
+    printf("write called\n");
+    pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); 
+    pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
+    unsigned char *buffer = (*env)->GetByteArrayElements(env, data, NULL);
+    int length = bytesRead;
+    int offset = indexJava;
+    buffer += offset;
+
+
+    pa_threaded_mainloop_lock(mainloop);
+  
+    while (length > 0) {
+
+	int available_size = pa_stream_writable_size(stream);
+        while (available_size == 0) {
+            pa_threaded_mainloop_wait(mainloop);
+            available_size = pa_stream_writable_size(stream);
+        }
+
+        if (available_size > length) {
+            available_size = length;
+        }
+
+        if (pa_stream_get_state(stream) != PA_STREAM_READY ) {
+            printf("stream errored!\n");
+            goto unlock_and_fail;
+        }
+
+        pa_stream_write(stream, buffer, available_size, NULL, 0, PA_SEEK_RELATIVE);
+        printf("written%d\n", available_size);
+      
+
+        buffer += available_size;
+        length -= available_size;
+       
+    }
+
+    pa_operation_unref(pa_stream_drain(stream, NULL, NULL));
+
+    pa_threaded_mainloop_unlock(mainloop);
+
+   
+    return;
+
+unlock_and_fail:
+    pa_threaded_mainloop_unlock(mainloop);
+fail:
+    return;
+
+}
+
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_closeStream
+  (JNIEnv *env, jobject obj) {
+	pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
+	printf("STREAM POINTER: %d\n", stream);
+  	pa_stream_disconnect(stream);
+}
+
+JNIEXPORT jint JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_available
+  (JNIEnv *env, jobject obj) {
+  	pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer");
+  	pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
+  	pa_threaded_mainloop_lock(mainloop);
+	int available = pa_stream_writable_size(stream);
+    	pa_threaded_mainloop_unlock(mainloop);
+    	return available;
+ }
+
+
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_drain
+  (JNIEnv *env, jobject obj) {
+  	pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer");
+  	pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
+  	pa_threaded_mainloop_lock(mainloop);
+	pa_operation *o = pa_stream_drain(stream, stream_operation_complete_cb, mainloop);
+    	while(pa_operation_get_state(o) != PA_OPERATION_DONE) {
+    		pa_threaded_mainloop_wait(mainloop);
+    	}
+    	pa_operation_unref(o);
+    	pa_threaded_mainloop_unlock(mainloop);
+ }
+
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_flush
+  (JNIEnv *env, jobject obj) {
+  	pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer");
+  	pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
+  	pa_threaded_mainloop_lock(mainloop);
+	pa_operation *o = pa_stream_flush(stream, stream_operation_complete_cb, mainloop);
+    	while(pa_operation_get_state(o) != PA_OPERATION_DONE) {
+    		pa_threaded_mainloop_wait(mainloop);
+    	}
+    	pa_operation_unref(o);
+    	pa_threaded_mainloop_unlock(mainloop);
+ }
+
+
+
+
+
+
--- a/src/org_openjdk_sound_PulseAudioSourceDataLine.h	Thu Jul 31 16:39:41 2008 -0400
+++ b/src/org_openjdk_sound_PulseAudioSourceDataLine.h	Thu Jul 31 17:29:47 2008 -0400
@@ -7,60 +7,78 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+#undef org_openjdk_sound_PulseAudioSourceDataLine_DEFAULT_BUFFER_SIZE
+#define org_openjdk_sound_PulseAudioSourceDataLine_DEFAULT_BUFFER_SIZE 1000L
 /*
  * Class:     org_openjdk_sound_PulseAudioSourceDataLine
- * Method:    openStream
- * Signature: (Ljava/lang/String;FIIZI)V
+ * Method:    native_open
+ * Signature: (ILjava/lang/String;Ljava/lang/String;FIIZI)V
  */
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_openStream
-  (JNIEnv *, jobject, jstring, jfloat, jint, jint, jboolean, jint);
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1open
+  (JNIEnv *, jobject, jint, jstring, jstring, jfloat, jint, jint, jboolean, jint);
 
 /*
  * Class:     org_openjdk_sound_PulseAudioSourceDataLine
- * Method:    writeToStream
+ * Method:    native_write
  * Signature: ([BII)V
  */
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_writeToStream
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1write
   (JNIEnv *, jobject, jbyteArray, jint, jint);
 
 /*
  * Class:     org_openjdk_sound_PulseAudioSourceDataLine
- * Method:    startStream
+ * Method:    native_get_writable_size
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1get_1writable_1size
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_openjdk_sound_PulseAudioSourceDataLine
+ * Method:    native_flush
  * Signature: ()V
  */
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_startStream
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1flush
   (JNIEnv *, jobject);
 
 /*
  * Class:     org_openjdk_sound_PulseAudioSourceDataLine
- * Method:    pauseStream
+ * Method:    native_start
  * Signature: ()V
  */
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_pauseStream
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1start
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_openjdk_sound_PulseAudioSourceDataLine
+ * Method:    native_pause
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1pause
   (JNIEnv *, jobject);
 
 /*
  * Class:     org_openjdk_sound_PulseAudioSourceDataLine
- * Method:    resumeStream
+ * Method:    native_resume
  * Signature: ()V
  */
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_resumeStream
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1resume
   (JNIEnv *, jobject);
 
 /*
  * Class:     org_openjdk_sound_PulseAudioSourceDataLine
- * Method:    drain
+ * Method:    native_drain
  * Signature: ()V
  */
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_drain
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1drain
   (JNIEnv *, jobject);
 
 /*
  * Class:     org_openjdk_sound_PulseAudioSourceDataLine
- * Method:    flush
+ * Method:    native_close
  * Signature: ()V
  */
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_flush
+JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1close
   (JNIEnv *, jobject);
 
 /*
@@ -71,14 +89,6 @@
 JNIEXPORT jint JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_available
   (JNIEnv *, jobject);
 
-/*
- * Class:     org_openjdk_sound_PulseAudioSourceDataLine
- * Method:    closeStream
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_closeStream
-  (JNIEnv *, jobject);
-
 #ifdef __cplusplus
 }
 #endif