changeset 31:70d51e08abbb

more merging committer: Omair Majid <omajid@redhat.com>
author Omair Majid <omajid@redhat.com>
date Fri, 01 Aug 2008 11:36:55 -0400
parents f05acd4ee58b
children e48962fa0e8e
files src/jni-common.c src/jni-common.h src/org/openjdk/sound/PulseAudioMixer.java src/org_openjdk_sound_EventLoop.c src/org_openjdk_sound_PulseAudioMixer.c src/org_openjdk_sound_PulseAudioSourceDataLine.c src/org_openjdk_sound_PulseAudioStreamVolumeControl.c src/org_openjdk_sound_PulseAudioTargetDataLine.c
diffstat 8 files changed, 271 insertions(+), 739 deletions(-) [+]
line wrap: on
line diff
--- a/src/jni-common.c	Fri Aug 01 11:22:31 2008 -0400
+++ b/src/jni-common.c	Fri Aug 01 11:36:55 2008 -0400
@@ -1,4 +1,31 @@
 #include "jni-common.h"
 
+void setJavaIntField(JNIEnv *env, jobject obj, void *ptr, char *fieldName) {
+	jclass cls = (*env)->GetObjectClass(env, obj);
+	jlong value = (int) ptr;
+	jfieldID fid =(*env)->GetFieldID(env, cls, fieldName, "I");
+	(*env)->SetIntField(env, obj, fid, value);
+	(*env)->DeleteLocalReference(cls);
+}
 
+void *getJavaIntField(JNIEnv *env, jobject obj, char *fieldName) {
+	jclass cls = (*env)->GetObjectClass(env, obj);
+	jfieldID fid = (*env)->GetFieldID(env, cls, fieldName, "I");
+	jlong value = (*env)->GetIntField(env, obj, fid);
+	(*env)->DeleteLocalReference(cls);
+	return (void *) value;
+}
 
+/*
+ * Throw an exception by name
+ */
+void ThrowByName(JNIEnv *env, const char *name, const char *msg) {
+	jclass cls = (*env)->FindClass(env, name);
+	/* if cls is NULL, an exception has already been thrown */
+	if (cls != NULL) {
+		(*env)->ThrowNew(env, cls, msg);
+	}
+	/* free the local ref */
+	(*env)->DeleteLocalRef(env, cls);
+}
+
--- a/src/jni-common.h	Fri Aug 01 11:22:31 2008 -0400
+++ b/src/jni-common.h	Fri Aug 01 11:36:55 2008 -0400
@@ -1,15 +1,14 @@
 #ifndef _JNI_COMMON_H
 #define _JNI_COMMON_H
 
-
 /*
  * This file contains some commonly used functions 
  * 
  */
 
-
-
+void *getJavaIntField(JNIEnv *env, jobject obj, char *fieldName);
+void setJavaIntField(JNIEnv *env, jobject obj, void *ptr, char *fieldName);
 
-
+void ThrowByName(JNIEnv *env, const char *name, const char *msg);
 
-#endif
\ No newline at end of file
+#endif
--- a/src/org/openjdk/sound/PulseAudioMixer.java	Fri Aug 01 11:22:31 2008 -0400
+++ b/src/org/openjdk/sound/PulseAudioMixer.java	Fri Aug 01 11:36:55 2008 -0400
@@ -31,7 +31,7 @@
 
 	private boolean isOpen = false;
 
-	 private List<PulseAudioSourceDataLine> _sourceLines = new ArrayList();
+	 private List<PulseAudioSourceDataLine> _sourceLines = new ArrayList<PulseAudioSourceDataLine>();
 	// private List<PulseAudioTargetDataLine> _targetLines = null;
 
 	private Line.Info _sourceDataLineInfo = new
--- a/src/org_openjdk_sound_EventLoop.c	Fri Aug 01 11:22:31 2008 -0400
+++ b/src/org_openjdk_sound_EventLoop.c	Fri Aug 01 11:36:55 2008 -0400
@@ -10,7 +10,7 @@
 	jobject obj;
 } java_context_t;
 
-java_context_t* java_context = NULL;
+static java_context_t* java_context = NULL;
 
 JNIEnv* pulse_thread_env = NULL;
 
--- a/src/org_openjdk_sound_PulseAudioMixer.c	Fri Aug 01 11:22:31 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,384 +0,0 @@
-#include "org_openjdk_sound_PulseAudioMixer.h"
-
-#include <stdio.h>
-#include <assert.h>
-
-#include <pulse/pulseaudio.h>
-
-/* FIXME
- *  jvm and native code scoping problems
- */
-typedef struct java_context_t {
-	pa_threaded_mainloop* mainloop;
-	JavaVM* jvm;
-	/* each JNIEnv* is valid for the thread that obtained it */
-	JNIEnv* env;				
-	JNIEnv* pulse_thread_env;
-} java_context_t;
-
-
-/*
- * store a structure with different JNIEnv pointers
- * so we can use it across threads
- */
-static java_context_t* java_context = NULL;
-
-
-/*
- * Throw an exception by name
- */
-static void ThrowByName(JNIEnv *env, const char *name, const char *msg) {
-	jclass cls = (*env)->FindClass(env, name);
-	/* if cls is NULL, an exception has already been thrown */
-	if (cls != NULL) {
-		(*env)->ThrowNew(env, cls, msg);
-	}
-	/* free the local ref */
-	(*env)->DeleteLocalRef(env, cls);
-}
-
-
-/*
- * do the actual callback
- * 
- * a good chance this method is running in a thread other than the main one
- * 
- */
-static void callback(JNIEnv* env) {
-	
-	/* find the instance of the Mixer */
-	char class_name[] = "org/openjdk/sound/PulseAudioMixer";
-    jclass cls = (*env)->FindClass(env, class_name);
-    if ( cls == NULL) {
-    	printf("class not found");
-    	return; /* class not found */
-    }
-    
-    jmethodID mid = (*env)->GetStaticMethodID(env, cls, "getInstance", "()Lorg/openjdk/sound/PulseAudioMixer;");
-    if (mid == NULL) {
-    	printf("method not found\n");
-        return;  /* method not found */
-    }
-    
-    jobject mixer = (*env)->CallStaticObjectMethod(env, cls, mid);
-    if ( mixer == NULL) {
-    	printf("unable to get mixer\n");
-    	return;
-    }
-    printf("after getting the mixer instance\n");
-    
-    
-    mid = (*env)->GetMethodID(env, cls, "callback", "()V");
-    if ( mid == NULL) {
-    	printf("unable to get callback method\n");
-    	return;
-    	
-    }
-	printf("got callback method\n");
-	
-	(*env)->CallVoidMethod(env, mixer, mid);
-	return;
-}
-
-
-/*
- * Class:     org_openjdk_sound_PulseAudioMixer
- * Method:    native_getStatus
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_org_openjdk_sound_PulseAudioMixer_native_1getStatus
-  (JNIEnv* env, jobject obj) {
-	jint result;
-	jclass cls = (*env)->GetObjectClass(env, obj);
-	
-	jfieldID fid = (*env)->GetFieldID(env, cls, "contextPointer", "I");
-	pa_context* context = (pa_context*) ((*env)->GetIntField(env, obj, fid));
-	
-	if ( context != NULL) {
-		result = pa_context_get_state(context);
-	} else  {
-		result = -1;
-	}
-	
-	if ( result != 1) {
-		jmethodID mid = (*env)->GetMethodID(env, cls, "notify", "()V");
-		(*env)->CallVoidMethod(env, obj, mid);
-	}
-	return result;
-}
-
-
-/* 
- * we need the separate thread for the pulseaudio's stuff 
- * so we need to attach the jvm to that thread.
- */
-static void attach_thread_to_jvm(java_context_t* j_context) {
-	assert(j_context);
-	assert(j_context->pulse_thread_env == NULL);
-	
-	printf("finding the JVM\n");
-
-	jsize actual_vms;
-	jint result = JNI_GetCreatedJavaVMs(&(j_context->jvm), 1, &actual_vms);
-	assert(result == 0);
-	//printf("JNI VM INFO: actual vm's created:%d\n", actual_vms);
-
-	printf("attaching to jvm...\n");
-	result = (*(j_context->jvm))->AttachCurrentThread((j_context->jvm), (void**)&(j_context->pulse_thread_env), NULL);
-			printf("attached to jvm\n");
-	assert(result == 0);
-
-//	ThrowByName(j_context->pulse_thread_env, "java/lang/UnsupportedOperationException", "Attached Native thread to jvm!");
-}
-
-
-/*
- * 
- * Detach the curren thread from the JVM
- * 
- */
-static void detach_thread_from_jvm(java_context_t* j_context) {
-	assert(j_context);
-	assert(j_context->pulse_thread_env);
-	//FIXME
-	j_context->pulse_thread_env = NULL;
-	(*(j_context->jvm))->DetachCurrentThread(j_context->jvm);
-}
-
-
-/*
- * want a call to a listener :(
- * 
- */
-static void context_drain_complete_cb(pa_context* context, void* userdata) {
-	return;
-}
-
-
-/* FIXME
- * problems: 
- *  ideally we want to tell some sort of listener on the java
- *  side that this eveven happened. question is, how to do that?
- *   - cant pass obj or env through userdata (scoping problems with jvm)
- * 
- * this method is called from either the java thread (on pa_context_connect())
- * or from the PulseAudio's thread. so its either a part of jvm, or needs to be 
- * attached to the jvm to be of use
- * 
- */
-static void context_state_cb(pa_context* context, void* userdata) {
-	assert(context);
-	
-	java_context_t* j_context = (java_context_t*)userdata;
-	pa_threaded_mainloop *mainloop = j_context->mainloop;
-
-	printf("context changed to %d\n", pa_context_get_state(context));
-	
-	static int attached = 0;
-
-	if (!attached) {
-		if (pa_context_get_state(context) != PA_CONTEXT_CONNECTING ) {
-			attached = 1;
-			attach_thread_to_jvm(j_context);
-		}
-	}
-	
-	if ( attached ) {
-		callback(j_context->pulse_thread_env);
-	} else {
-		callback(j_context->env);
-	}
-	
-	switch (pa_context_get_state(context)) {
-	case PA_CONTEXT_CONNECTING:
-		break;
-	case PA_CONTEXT_READY:
-//		ThrowByName(j_context->pulse_thread_env, "java/lang/UnsupportedOperationException", "Context connected");
-		
-		pa_threaded_mainloop_signal(mainloop, 0);
-
-		break;
-	case PA_CONTEXT_TERMINATED:
-		/* connection has sanely terminated
-		 */
-
-		if (attached) {
-			attached = 0;
-//			ThrowByName(j_context->pulse_thread_env, "java/lang/UnsupportedOperationException", "Context terminated");
-
-			detach_thread_from_jvm(j_context);
-		} else {
-//			ThrowByName(j_context->env, "java/lang/UnsupportedOperationException", "context terminated");
-		}
-		printf("ERROR: CONTEXT_TERMINATED\n");
-
-		pa_threaded_mainloop_signal(mainloop, 0);
-		break;
-		
-	case PA_CONTEXT_FAILED:
-		/* this can happen before we connect (ie error connecting to server)
-		 * or after we connect. so check whether we are connected, 
-		 * and then use the appropriate thread(env) to send the exception
-		 */
-		pa_threaded_mainloop_signal(mainloop, 0);
-
-		if (attached) {
-//			ThrowByName(j_context->pulse_thread_env, "java/lang/UnsupportedOperationException", "context failed");
-//			callback(j_context->pulse_thread_env);
-			attached = 0;
-			detach_thread_from_jvm(j_context);
-		} else {
-//			ThrowByName(j_context->env, "java/lang/UnsupportedOperationException", "context failed");
-		}
-		printf("ERROR: CONTEXT_FAILED\n");
-
-		//TODO throw an exception here?
-		// this does happen when we are trying to quit as well
-		break;
-	default:
-		break;
-	}
-}
-
-/*
- * Class:     org_openjdk_sound_PulseAudioMixer
- * Method:    native_initialize
- * Signature: (Ljava/lang/String;Ljava/lang/String;)V
- */
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioMixer_native_1initialize
-(JNIEnv* env, jobject obj, jstring appName, jstring server) {
-
-	jfieldID fid;       /* the field id */
-	jclass cls = (*env)->GetObjectClass(env,obj);
-
-	printf("native_initialize() called\n");
-	pa_threaded_mainloop *mainloop = pa_threaded_mainloop_new();
-	assert(mainloop != NULL);
-	pa_mainloop_api *mainloop_api = pa_threaded_mainloop_get_api(mainloop);
-	assert(mainloop != NULL);
-
-	pa_context *context = NULL;
-
-	assert(appName != NULL);
-
-	const jbyte* string_appName;
-	string_appName = (*env)->GetStringUTFChars(env, appName, NULL);
-	if (string_appName == NULL) {
-		return;        /* a OutOfMemoryError thrown by vm */
-	}
-	printf("using appName : %s\n", string_appName);
-	context = pa_context_new(mainloop_api, string_appName);
-	assert(mainloop != NULL);
-	(*env)->ReleaseStringUTFChars(env, appName, string_appName);
-
-	java_context = malloc(sizeof(java_context_t));
-	java_context->mainloop = mainloop;
-	java_context->env = env;
-	java_context->pulse_thread_env = NULL;
-	
-	
-	pa_context_set_state_callback(context, context_state_cb, java_context);
-
-	if (server != NULL) {
-		const jbyte* string_server = NULL;
-		string_server = (*env)->GetStringUTFChars(env, server, NULL);
-		if (string_server == NULL) {
-			return;	/* OutOfMemoryError */
-		}
-		printf("About to connect to server: %s\n", string_server);
-		pa_context_connect(context, string_server, 0, NULL);
-		(*env)->ReleaseStringUTFChars(env, appName, string_server);
-	} else {
-		printf("using default server\n");
-		pa_context_connect(context, NULL, 0, NULL);
-	}
-
-	pa_threaded_mainloop_lock(mainloop);
-	pa_threaded_mainloop_start(mainloop);
-	pa_threaded_mainloop_wait(mainloop);	// wait for the context to initialize
-
-	if ( pa_context_get_state(context) != PA_CONTEXT_READY ) {
-		printf("ERROR: context initialization failed\n");
-		goto unlock_and_fail;
-	}
-
-	pa_threaded_mainloop_unlock(mainloop);
-
-	fid = (*env)->GetFieldID(env, cls, "mainloopPointer", "I");
-	(*env)->SetIntField(env, obj, fid, (jint)mainloop);
-
-	fid = (*env)->GetFieldID(env, cls, "contextPointer", "I");
-	(*env)->SetIntField(env, obj, fid, (jint) context);
-
-	printf("native_initialize() returning\n");
-	return;
-	
-unlock_and_fail:
-	printf("about to wait");
-
-	jmethodID mid = (*env)->GetMethodID(env, cls, "wait", "()V");
-	(*env)->CallVoidMethod(env, obj, mid);
-
-	ThrowByName(env, "java/lang/UnsupportedOperationException", "Mixer initialization failed");
-
-	pa_threaded_mainloop_unlock(mainloop);
-	pa_threaded_mainloop_stop(mainloop);
-	pa_threaded_mainloop_free(mainloop);
-
-	mainloop = NULL;
-	context = NULL;
-	
-	fid = (*env)->GetFieldID(env, cls, "mainloopPointer", "I");
-	(*env)->SetIntField(env, obj, fid, (jint)mainloop);
-
-	fid = (*env)->GetFieldID(env, cls, "contextPointer", "I");
-	(*env)->SetIntField(env, obj, fid, (jint) context);
-	
-	return;
-}
-
-/*
- * Class:     org_openjdk_sound_PulseAudioMixer
- * Method:    native_shutdown
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioMixer_native_1shutdown
-(JNIEnv * env, jobject obj) {
-
-	printf("native_shutdown() starting\n");
-
-	jfieldID fid;       /* the field id */
-	jclass cls = (*env)->GetObjectClass(env,obj);
-
-	fid = (*env)->GetFieldID(env, cls, "mainloopPointer", "I");
-	pa_threaded_mainloop* mainloop = (pa_threaded_mainloop*) ((*env)->GetIntField(env, obj, fid));
-	assert(mainloop != NULL);
-
-	fid = (*env)->GetFieldID(env, cls, "contextPointer", "I");
-	pa_context* context = (pa_context*) ((*env)->GetIntField(env, obj, fid));
-	assert(context != NULL);
-
-	printf("trying to acquire lock\n");
-	pa_threaded_mainloop_lock(mainloop);
-	printf("got lock\n");
-	
-	pa_operation* o = pa_context_drain(context, context_drain_complete_cb, NULL);
-	/* o is NULL if there is nothing to drain */
-	if (o != NULL) {
-		while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
-			pa_threaded_mainloop_wait(mainloop);
-		}
-		pa_operation_unref(o);
-	}
-
-	pa_context_disconnect(context);
-
-	pa_threaded_mainloop_unlock(mainloop);
-	pa_threaded_mainloop_stop(mainloop);
-	pa_threaded_mainloop_free(mainloop);
-
-	free(java_context);
-	
-	printf("native_shutdown() returning\n");
-}
-
--- a/src/org_openjdk_sound_PulseAudioSourceDataLine.c	Fri Aug 01 11:22:31 2008 -0400
+++ b/src/org_openjdk_sound_PulseAudioSourceDataLine.c	Fri Aug 01 11:36:55 2008 -0400
@@ -5,28 +5,12 @@
 #include <pulse/pulseaudio.h>
 #include "org_openjdk_sound_PulseAudioSourceDataLine.h"
 
-void setJavaIntField(JNIEnv *env, jobject obj, void *ptr, char *fieldName) {
-	jclass cls = (*env)->GetObjectClass(env, obj);
-	jlong value = (int) ptr;
-	jfieldID fid =(*env)->GetFieldID(env, cls, fieldName, "I");
-	(*env)->SetIntField(env, obj, fid, value);
-	(*env)->DeleteLocalReference(cls);
-}
-
-void *getJavaIntField(JNIEnv *env, jobject obj, char *fieldName) {
-    jclass cls = (*env)->GetObjectClass(env, obj);
-	jfieldID fid = (*env)->GetFieldID(env, cls, fieldName, "I");
-	jlong value = (*env)->GetIntField(env, obj, fid);
-	(*env)->DeleteLocalReference(cls);
-	return (void *) value;
-}
-
-
 typedef struct java_context_t {
 	JNIEnv* env;
 	jobject obj;
 } java_context_t;
 
+static java_context_t* java_context;
 
 /* defined in EventLoop.c */
 extern JNIEnv* pulse_thread_env;
@@ -47,7 +31,7 @@
 
 	java_context_t* java_context = (java_context_t*)userdata;
 	JNIEnv* env;
-	
+
 	/* needed so we can create a stream from another thread
 	 */
 	if (pa_stream_get_state(stream) == PA_STREAM_CREATING) {
@@ -83,68 +67,6 @@
 
 }
 
-
-
-typedef struct java_context_t {
-	JNIEnv* env;
-	jobject obj;
-} java_context_t;
-
-
-/* defined in EventLoop.c */
-extern JNIEnv* pulse_thread_env;
-
-
-
-static void stream_state_change_callback(pa_stream* stream, void* userdata) {
-	assert(stream);
-	assert(userdata);
-
-	printf("entering stream_state_change_callback\n");
-
-	java_context_t* java_context = (java_context_t*)userdata;
-	JNIEnv* env;
-	
-	/* needed so we can create a stream from another thread
-	 */
-	if (pa_stream_get_state(stream) == PA_STREAM_CREATING) {
-		printf("java thread\n");
-		env = java_context->env;
-	} else {
-		env = pulse_thread_env;
-	}
-
-	jobject obj = java_context->obj;
-
-	printf("stream state changed to %d\n", pa_stream_get_state(stream));
-
-	/* Call the 'update' method in java
-	 * to handle all java-side events
-	 */
-	jclass cls = (*env)->GetObjectClass(env, obj);
-	if (cls == NULL) {
-		printf("unable to get class of object");
-		return;
-	}
-	jmethodID mid = (*env)->GetMethodID(env, cls, "update", "(I)V");
-	if (mid == NULL) {
-		printf("unable to get callback method\n");
-		return;
-
-	}
-	printf("calling update on java\n");
-	(*env)->CallVoidMethod(env, obj, mid, pa_stream_get_state(stream));
-
-	printf("returning form stream_state_change_callback\n");
-	return;
-
-}
-
-
-
-
-
-
 /*
  * Class:     org_openjdk_sound_PulseAudioSourceDataLine
  * Method:    native_open
@@ -163,31 +85,31 @@
 	pa_context* context = (pa_context*) contextPointer;
 	assert(context != NULL);
 
-    pa_sample_spec sample_spec;
-    
-    char *encoding = (*env)->GetStringUTFChars(env, encodingString, 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");
-     	//TODO: Invalid format :throw Exception;
-     }
-    
-    sample_spec.rate = rate;
-    sample_spec.channels = channels;
+	pa_sample_spec sample_spec;
+
+	char *encoding = (*env)->GetStringUTFChars(env, encodingString, 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");
+		//TODO: Invalid format :throw Exception;
+	}
+
+	sample_spec.rate = rate;
+	sample_spec.channels = channels;
 
 	/* obtain the server from the caller */
 	const jbyte* stream_name = NULL;
@@ -200,9 +122,9 @@
 	assert(stream != NULL);
 	(*env)->ReleaseStringUTFChars(env, name, stream_name);
 
-    pa_stream_set_state_callback(stream, stream_state_change_callback, java_context);
-  
-    setJavaIntField(env, obj, stream, "streamPointer");    
+	pa_stream_set_state_callback(stream, stream_state_change_callback, java_context);
+
+	setJavaIntField(env, obj, stream, "streamPointer");
 	printf("returning from native_open\n");
 
 }
@@ -218,7 +140,7 @@
 	jclass cls = (*env)->GetObjectClass(env, obj);
 	jfieldID fid = (*env)->GetFieldID(env, cls, "streamPointer", "I");
 	assert(fid);
-	
+
 	pa_stream* stream = (pa_stream*) (*env)->GetIntField(env, obj, fid);
 	jbyte* data_buffer = (*env)->GetByteArrayElements(env, data, NULL);
 
@@ -260,11 +182,10 @@
 JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1start
 (JNIEnv *env, jobject obj) {
 	printf("start called\n");
-  
-    pa_stream *stream = getJavaIntField(env, obj, "streamPointer");
 
-    pa_stream_connect_playback(stream, NULL, NULL, 0, NULL, NULL);
+	pa_stream *stream = getJavaIntField(env, obj, "streamPointer");
 
+	pa_stream_connect_playback(stream, NULL, NULL, 0, NULL, NULL);
 
 }
 
--- a/src/org_openjdk_sound_PulseAudioStreamVolumeControl.c	Fri Aug 01 11:22:31 2008 -0400
+++ b/src/org_openjdk_sound_PulseAudioStreamVolumeControl.c	Fri Aug 01 11:36:55 2008 -0400
@@ -2,7 +2,7 @@
 #include <pulse/pulseaudio.h>
 #include "org_openjdk_sound_PulseAudioStreamVolumeControl.h"
 
-typedef struct{
+typedef struct {
 	pa_threaded_mainloop *mainloop;
 	pa_cvolume *volume;
 } userdata_info;
@@ -15,41 +15,43 @@
 	return (void *) value;
 }
 
-static void sink_input_change_volume(pa_context* context, const pa_sink_input_info* sink_input_info, int eol, void* userdata) {
+static void sink_input_change_volume(pa_context* context,
+		const pa_sink_input_info* sink_input_info, int eol, void* userdata) {
 	assert(context);
 	if (eol) {
 		return;
-  	}
+	}
 	assert(sink_input_info);
-	
-	
- 	(((userdata_info *) userdata)->volume)->channels = sink_input_info->volume.channels;
- 	int j;
- 	for (j = 0; j < (((userdata_info *)userdata)->volume)->channels; j++) {
-		(((userdata_info *)userdata)->volume)->values[j] = sink_input_info->volume.values[j];
- 	}
- 	pa_threaded_mainloop_signal(((userdata_info *) userdata)->mainloop, 0);
- 	
+
+	(((userdata_info *) userdata)->volume)->channels
+			= sink_input_info->volume.channels;
+	int j;
+	for (j = 0; j < (((userdata_info *)userdata)->volume)->channels; j++) {
+		(((userdata_info *)userdata)->volume)->values[j]
+				= sink_input_info->volume.values[j];
+	}
+	pa_threaded_mainloop_signal(((userdata_info *) userdata)->mainloop, 0);
+
 }
 
-JNIEXPORT jfloat JNICALL Java_org_openjdk_sound_PulseAudioStreamVolumeControl_getValue(JNIEnv *env, jobject obj)  {
-	 pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
-	 pa_threaded_mainloop *mainloop = getJavaLongField(env, obj, "mainLoopPointer");
-	 pa_context *context = pa_stream_get_context(stream);
-	 int stream_id = pa_stream_get_index(stream);
-	
-	 userdata_info *userdata =  malloc(sizeof(userdata_info));
-	 userdata->mainloop = mainloop;
-	 userdata->volume = malloc(sizeof(pa_cvolume));
-	 pa_threaded_mainloop_lock(mainloop);
-	 pa_operation *o = pa_context_get_sink_input_info((pa_context*) context ,stream_id,sink_input_change_volume, userdata);
-    	 while(pa_operation_get_state(o) != PA_OPERATION_DONE) {
-    		pa_threaded_mainloop_wait(mainloop);
-    	}
-    	pa_operation_unref(o);
-    	pa_threaded_mainloop_unlock(mainloop);
+JNIEXPORT jfloat JNICALL Java_org_openjdk_sound_PulseAudioStreamVolumeControl_getValue(JNIEnv *env, jobject obj) {
+	pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
+	pa_threaded_mainloop *mainloop = getJavaLongField(env, obj, "mainLoopPointer");
+	pa_context *context = pa_stream_get_context(stream);
+	int stream_id = pa_stream_get_index(stream);
+
+	userdata_info *userdata = malloc(sizeof(userdata_info));
+	userdata->mainloop = mainloop;
+	userdata->volume = malloc(sizeof(pa_cvolume));
+	pa_threaded_mainloop_lock(mainloop);
+	pa_operation *o = pa_context_get_sink_input_info((pa_context*) context ,stream_id,sink_input_change_volume, userdata);
+	while(pa_operation_get_state(o) != PA_OPERATION_DONE) {
+		pa_threaded_mainloop_wait(mainloop);
+	}
+	pa_operation_unref(o);
+	pa_threaded_mainloop_unlock(mainloop);
 	return pa_sw_volume_to_dB(userdata->volume->values[0]);
-	 
+
 }
 
 JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioStreamVolumeControl_setValue (JNIEnv *env, jobject obj, jfloat new_volume) {
@@ -61,5 +63,3 @@
 	pa_context_set_sink_input_by_index(context, stream_id, pa_cvolume_set(&cv, channels, pa_sw_volume_from_dB(new_volume)), NULL, NULL);
 }
 
-
-
--- a/src/org_openjdk_sound_PulseAudioTargetDataLine.c	Fri Aug 01 11:22:31 2008 -0400
+++ b/src/org_openjdk_sound_PulseAudioTargetDataLine.c	Fri Aug 01 11:36:55 2008 -0400
@@ -4,256 +4,225 @@
 #include <jni.h>
 #include <pulse/pulseaudio.h>
 #include <string.h>
+
 #include "org_openjdk_sound_PulseAudioTargetDataLine.h"
-
-
-
-
-
+#include "jni-common.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);
+static void stream_read_cb(pa_stream* stream, size_t length, void* userdata) {
+	pa_threaded_mainloop *mainloop = userdata;
+	pa_threaded_mainloop_signal(mainloop, 0);
 }
 
-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_operation_complete_cb(pa_stream* stream, int success,
+		void* userdata) {
+	pa_threaded_mainloop *mainloop = userdata;
+	pa_threaded_mainloop_signal(mainloop, 0);
 }
 
-
-
-static void stream_read_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:
-        case PA_STREAM_TERMINATED:
-            pa_threaded_mainloop_signal(mainloop, 0);
-            break;
+	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:
+	case PA_STREAM_TERMINATED:
+		pa_threaded_mainloop_signal(mainloop, 0);
+		break;
 
-        default:
-            /* do nothing */
-            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
+(JNIEnv * env, jobject obj, jstring string, jfloat rate, jint size, jint channels, jboolean bigEndian, jint bufferSize) {
+
+	printf("entering native_open\n");
+
+	pa_context* context = (pa_context*) contextPointer;
+	assert(context != NULL);
+
+	obj = (*env)->NewGlobalRef(env, obj);
+
+	java_context_t* java_context = malloc(sizeof(java_context));
+	java_context->env = env;
+	java_context->obj = obj;
+
+	//TODO: Need to deal with the buffer size. Currently ignored
+
+	pa_sample_spec sample_spec;
+
+	char *encoding = GetStringUTFChars(env, string, NULL);
 
-    pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); 
-    pa_context *context = getJavaLongField(env, obj, "contextPointer");
-    
-   
-    pa_sample_spec sample_spec;
-    
-    char *encoding = 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 {
-     	//TO DO: Invalid format :throw Exception;
-     }
-    
-    sample_spec.rate = rate;
-    sample_spec.channels = channels;
+	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 {
+		//TODO: Invalid format :throw Exception;
+	}
 
-    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_read_callback(stream, stream_read_cb, mainloop);
-    
-  
-    pa_threaded_mainloop_unlock(mainloop);
+	sample_spec.rate = rate;
+	sample_spec.channels = channels;
 
-
-    setJavaLongField(env, obj, stream, "streamPointer");    
-    return;
+	/* obtain the server from the caller */
+	const jbyte* stream_name = NULL;
+	stream_name = (*env)->GetStringUTFChars(env, name, NULL);
+	if (stream_name == NULL) {
+		return; /* OutOfMemoryError */
+	}
+	printf("About to create stream: %s\n", stream_name);
+	pa_stream* stream = pa_stream_new(context, stream_name, &sample_spec, NULL);
+	assert(stream != NULL);
+	(*env)->ReleaseStringUTFChars(env, name, stream_name);
 
-unlock_and_fail:
-    pa_threaded_mainloop_unlock(mainloop);
+	pa_stream_set_state_callback(stream, stream_state_change_callback, java_context);
 
-fail:
-    return;
+	jclass cls = (*env)->GetObjectClass(env,obj);
+	jfieldID fid = (*env)->GetFieldID(env, cls, "streamPointer", "I");
+	(*env)->SetIntField(env, obj, fid, (jint) stream);
+
+	printf("returning from native_open\n");
+
 }
 
 JNIEXPORT void JNICALL
 Java_org_openjdk_sound_PulseAudioSourceDataLine_startStream(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_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);
+	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_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 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);
 }
-  
-
 
 J
 
 JNIEXPORT void JNICALL
 Java_org_openjdk_sound_PulseAudioSourceDataLine__closeStream(JNIEnv *env, jobject obj, jint channels, jfloat rate) {
 
-    
- 
-  	pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
-  	pa_strean_disconnect(stream);
+	pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
+	pa_strean_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);
+(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;
- }
-
+	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);
+(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);
- }
+	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);
+(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);
- }
-
-
-
-
+	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_PulseAudioTargetDataLine_readFromStream
-  (JNIEnv * env, jobject obj, jbyteArray array, jint length, jint offset);
-	pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer");
-  	pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
-	pa_threaded_mainloop_lock(mainloop);
-	char[length] data;
-	while(length > 0) {
-		size_t l;
-		while(!read_data) {
-			int r = pa_stream_peek(_stream, &read_data, &read_length);
-			if(!read_data) {
-				pa_threaded_mainloop_wait(mainloop);
-			} else {
-				read_index = 0;
-			}			
+(JNIEnv * env, jobject obj, jbyteArray array, jint length, jint offset);
+pa_threaded_mainloop *mainloop = getJavaLongField(env, obj, "mainLoopPointer");
+pa_stream *stream = getJavaLongField(env, obj, "streamPointer");
+pa_threaded_mainloop_lock(mainloop);
+char[length] data;
+while(length> 0) {
+	size_t l;
+	while(!read_data) {
+		int r = pa_stream_peek(_stream, &read_data, &read_length);
+		if(!read_data) {
+			pa_threaded_mainloop_wait(mainloop);
+		} else {
+			read_index = 0;
 		}
-		
-		l = read_length < length ? read_length : length;
-		memcpy(data, read_data+read_index, l);
-		
-		data = data + l;
-		length -= l;
-		read_index +=l;
-		read_length-=l;
-		
-		if(! read_length) {
-			int r = pa_stream_drop(stream);
-			read_data = NULL;
-			read_length = 0;
-			read_index = 0;
-			
-		}
-		
-		
 	}
-	
-	pa_threaded_mainloop_unlock(mainloop);
-	SetByteArrayRegion(env, array, offset, initialLength, data);
+
+	l = read_length < length ? read_length : length;
+	memcpy(data, read_data+read_index, l);
+
+	data = data + l;
+	length -= l;
+	read_index +=l;
+	read_length-=l;
+
+	if(! read_length) {
+		int r = pa_stream_drop(stream);
+		read_data = NULL;
+		read_length = 0;
+		read_index = 0;
+
+	}
+
 }
 
-
-
-
+pa_threaded_mainloop_unlock(mainloop);
+SetByteArrayRegion(env, array, offset, initialLength, data);
+}
 
-    
-
-
-