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