Mercurial > hg > pulseaudio
changeset 37:127841aeb6e9
added flush() and drain() to SourceDataLine
committer: Ioana Ivan <iivan@redhat.com>
author | Ioana Ivan <iivan@redhat.com> |
---|---|
date | Fri, 01 Aug 2008 12:12:03 -0400 |
parents | a22db30b1290 (current diff) 73125e09b897 (diff) |
children | 92e04ec1b947 |
files | src/PulseAudioMixer.c src/PulseAudioMixer.h src/PulseAudioSourceDataLine.c src/PulseAudioSourceDataLine.h src/PulseAudioTargetDataLine.c src/org/openjdk/sound/PulseAudioMixer.java src/org/openjdk/sound/PulseAudioSourceDataLine.java src/org_openjdk_sound_PulseAudioMixer.c src/org_openjdk_sound_PulseAudioSourceDataLine.c src/org_openjdk_sound_PulseAudioSourceDataLine.c_ORIGINAL src/org_openjdk_sound_PulseAudioSourceDataLine.h |
diffstat | 18 files changed, 367 insertions(+), 1600 deletions(-) [+] |
line wrap: on
line diff
--- a/makefile Fri Aug 01 12:07:21 2008 -0400 +++ b/makefile Fri Aug 01 12:12:03 2008 -0400 @@ -22,7 +22,8 @@ lib/libpulse-java.so: \ bin/org_openjdk_sound_EventLoop.o \ - bin/org_openjdk_sound_PulseAudioSourceDataLine.o + bin/org_openjdk_sound_PulseAudioSourceDataLine.o \ + bin/jni-common.o # bin/org_openjdk_sound_PulseAudioTargetDataLine.o gcc -g -shared -o $@ $^ /usr/lib/libpulse.so @@ -37,6 +38,9 @@ #bin/org_openjdk_sound_PulseAudioTargetDataLine.o: src/org_openjdk_sound_PulseAudioTargetDataLine.c src/org_openjdk_sound_PulseAudioTargetDataLine.h bin # gcc -g -c -o $@ $< +bin/jni-common.o: src/jni-common.c src/jni-common.h + gcc -g -c -o $@ $< + # Java headers src/org_openjdk_sound_EventLoop.h: src/org/openjdk/sound/EventLoop.class
--- a/src/PulseAudioMixer.c Fri Aug 01 12:07:21 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -#include <jni.h> -#include <pulse/pulseaudio.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 context_state_cb(pa_context* context, void* userdata) { - assert(context); - pa_threaded_mainloop *mainloop = userdata; - switch (pa_context_get_state(context)) { - case PA_CONTEXT_READY: - case PA_CONTEXT_TERMINATED: - case PA_CONTEXT_FAILED: - pa_threaded_mainloop_signal(mainloop, 0); - break; - default: - break; - } -} - -JNIEXPORT void JNICALL Java_PulseAudioMixer_initialize(JNIEnv *env, jobject obj) { - - //TO DO :check return value for system calls - pa_threaded_mainloop *mainloop = pa_threaded_mainloop_new(); - pa_mainloop_api *mainloop_api = pa_threaded_mainloop_get_api(mainloop); - pa_context *context = pa_context_new(mainloop_api, "Java app"); - - pa_context_set_state_callback(context, context_state_cb, mainloop); - pa_context_connect(context, NULL, 0, NULL); - - pa_threaded_mainloop_lock(mainloop); - - pa_threaded_mainloop_start(mainloop); - - pa_threaded_mainloop_wait(mainloop); - - if ( pa_context_get_state(context) != PA_CONTEXT_READY ) { - printf("context initialization failed\n"); - } - - pa_threaded_mainloop_unlock(mainloop); - - setJavaLongField(env, obj, context, "contextPointer"); - setJavaLongField(env, obj, mainloop, "mainLoopPointer"); -} - - - - - -
--- a/src/PulseAudioMixer.h Fri Aug 01 12:07:21 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include <jni.h> -/* Header for class PulseAudioMixer */ - -#ifndef _Included_PulseAudioMixer -#define _Included_PulseAudioMixer -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: PulseAudioMixer - * Method: initialize - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_PulseAudioMixer_initialize - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif
--- a/src/PulseAudioSourceDataLine.c Fri Aug 01 12:07:21 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,267 +0,0 @@ -#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: - case PA_STREAM_TERMINATED: - 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 = 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; - - 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_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); -} - -JNIEXPORT void JNICALL Java_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 JNICALL Java_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_PulseAudioSourceDataLine_writeToStream(JNIEnv *env, jobject obj, jbyteArray data, jint bytesRead, jint indexJava) { - 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); - - - 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_PulseAudioSourceDataLine_closeConnection(JNIEnv *env, jobject obj, jint channels, jfloat rate) { - - - pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); - pa_stream *stream = getJavaLongField(env, obj, "streamPointer"); - - printf("pulse_shutdown() called\n"); - - 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); - - //pa_threaded_mainloop_stop(mainloop); - //pa_threaded_mainloop_free(mainloop); -} - -JNIEXPORT jint JNICALL Java_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 jint JNICALL Java_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 jint JNICALL Java_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/PulseAudioSourceDataLine.h Fri Aug 01 12:07:21 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include <jni.h> -/* Header for class PulseAudioSourceDataLine */ - -#ifndef _Included_PulseAudioSourceDataLine -#define _Included_PulseAudioSourceDataLine -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: PulseAudioSourceDataLine - * Method: openStream - * Signature: (IF)V - */ -JNIEXPORT void JNICALL Java_PulseAudioSourceDataLine_openStream - (JNIEnv *, jobject, jint, jfloat); - -/* - * Class: PulseAudioSourceDataLine - * Method: write - * Signature: ([BIILjava/lang/String;)V - */ -JNIEXPORT void JNICALL Java_PulseAudioSourceDataLine_write - (JNIEnv *, jobject, jbyteArray, jint, jint, jstring); - -/* - * Class: PulseAudioSourceDataLine - * Method: closeConnection - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_PulseAudioSourceDataLine_closeConnection - (JNIEnv *, jobject); - -/* - * Class: PulseAudioSourceDataLine - * Method: startStream - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_PulseAudioSourceDataLine_startStream - (JNIEnv *, jobject); - -/* - * Class: PulseAudioSourceDataLine - * Method: pauseStream - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_PulseAudioSourceDataLine_pauseStream - (JNIEnv *, jobject); - -/* - * Class: PulseAudioSourceDataLine - * Method: resumeStream - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_PulseAudioSourceDataLine_resumeStream - (JNIEnv *, jobject); - -/* - * Class: PulseAudioSourceDataLine - * Method: available - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_PulseAudioSourceDataLine_available - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif
--- a/src/PulseAudioTargetDataLine.c Fri Aug 01 12:07:21 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,197 +0,0 @@ -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> -#include <jni.h> -#include <pulse/pulseaudio.h> -#include <string.h> - - -const char* const APP_NAME = "simple-rec"; - -pa_threaded_mainloop* _mainloop = NULL; -pa_mainloop_api* _mainloop_api = NULL; -pa_context* _context = NULL; -pa_stream* _stream = NULL; -const void *read_data = NULL; -size_t read_index, read_length; - - -pa_sample_spec _sample_spec; - -static void stream_read_cb(pa_stream* stream, size_t length, void* userdata) { - - pa_threaded_mainloop_signal(_mainloop,0); -} - -static void stream_drain_complete_cb(pa_stream* stream, int success, void* userdata) { - pa_threaded_mainloop_signal(_mainloop,0); -} - - - - -static void stream_state_cb(pa_stream* stream, void* userdata) { - assert(stream); - - 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; - } - } - -static void context_state_cb(pa_context* context, void* userdata) { - assert(context); - - printf("context state changed to %d\n", pa_context_get_state(context)); - - switch (pa_context_get_state(context)) { - case PA_CONTEXT_READY: - case PA_CONTEXT_TERMINATED: - case PA_CONTEXT_FAILED: - pa_threaded_mainloop_signal(_mainloop, 0); - break; - default: - /* do nothing */ - break; - } -} - -static void init_streams(void) { - _sample_spec.format = PA_SAMPLE_S16LE; - _sample_spec.rate = 44100; - _sample_spec.channels = 2; - - _stream = pa_stream_new(_context, "default stream", &_sample_spec, NULL); - - pa_stream_set_state_callback(_stream, stream_state_cb, NULL); - pa_stream_set_read_callback(_stream, stream_read_cb, NULL); - - - - int check = pa_stream_connect_record(_stream, NULL, NULL, 0); - if(check < 0) { - printf("couldn't connect\n"); - } - - /* wait for stream to initilize */ - pa_threaded_mainloop_wait(_mainloop); - - if (pa_stream_get_state(_stream) != PA_STREAM_READY) { - printf("stream initialization failed\n"); - } -} - -static void pulse_init(void) { - - printf("pulse_init() called\n"); - - - _mainloop = pa_threaded_mainloop_new(); - _mainloop_api = pa_threaded_mainloop_get_api(_mainloop); - _context = pa_context_new(_mainloop_api, APP_NAME); - - pa_context_set_state_callback(_context, context_state_cb, NULL); - pa_context_connect(_context, NULL, 0, NULL); - - pa_threaded_mainloop_lock(_mainloop); - - pa_threaded_mainloop_start(_mainloop); - /* wait for context to be ready */ - pa_threaded_mainloop_wait(_mainloop); - - if ( pa_context_get_state(_context) != PA_CONTEXT_READY ) { - printf("context initialization failed\n"); - goto unlock_and_fail; - } - - - init_streams(); - - pa_threaded_mainloop_unlock(_mainloop); - - printf("pulse_init() returning\n"); - return; - -unlock_and_fail: - pa_threaded_mainloop_unlock(_mainloop); - -fail: - return; -} - -int pulse_read (void *data, size_t length) { - printf("IN READ\n"); - pa_threaded_mainloop_lock(_mainloop); - while(length > 0) { - size_t l; - while(!read_data) { - int r = pa_stream_peek(_stream, &read_data, &read_length); - //printf("read length = %d\n", 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); -} - -void closeConnection() { - printf("pulse_shutdown() called\n"); - - pa_threaded_mainloop_lock(_mainloop); - pa_operation *o = pa_stream_drain(_stream, stream_drain_complete_cb, NULL); - while(pa_operation_get_state(o) != PA_OPERATION_DONE) { - pa_threaded_mainloop_wait(_mainloop); - } - pa_operation_unref(o); - pa_threaded_mainloop_unlock(_mainloop); - - pa_threaded_mainloop_stop(_mainloop); - pa_threaded_mainloop_free(_mainloop); - - printf("pulse_shutdown() returning\n"); - return; -} - - -int main() { - pulse_init(); - uint8_t buf[10000]; - pulse_read(buf, 10000); - //write(1, buf, 10000); - //closeConnection(); - -} - - - - -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jni-common.c Fri Aug 01 12:12:03 2008 -0400 @@ -0,0 +1,30 @@ +#include "jni-common.h" + +void setJavaIntField(JNIEnv *env, jobject obj,char *fieldName, int value) { + jclass cls = (*env)->GetObjectClass(env, obj); + jfieldID fid =(*env)->GetFieldID(env, cls, fieldName, "I"); + (*env)->SetIntField(env, obj, fid, value); + (*env)->DeleteLocalRef(env, 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)->DeleteLocalRef(env, 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); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jni-common.h Fri Aug 01 12:12:03 2008 -0400 @@ -0,0 +1,15 @@ +#ifndef _JNI_COMMON_H +#define _JNI_COMMON_H + +#include <jni.h> +/* + * This file contains some commonly used functions + * + */ + +void* getJavaIntField(JNIEnv* env, jobject obj, char* fieldName); +void setJavaIntField(JNIEnv* env, jobject obj, char* fieldName, int value); + +void throwByName(JNIEnv* const env, const char* const name, const char* const msg); + +#endif
--- a/src/org/openjdk/sound/EventLoop.java Fri Aug 01 12:07:21 2008 -0400 +++ b/src/org/openjdk/sound/EventLoop.java Fri Aug 01 12:12:03 2008 -0400 @@ -49,7 +49,16 @@ private native void native_set_sink_volume(int contextPointer, int streamPointer, int volume); - // pointers + /* + * These fields hold pointers + * + * When going from 32 bit to 64 bit, these will have to be changed to longs, + * but not otherwise + * + * Pointer sizes change from 32 bit to 64 bit, but java data types's sizes + * dont + * + */ @SuppressWarnings("unused") private int contextPointer; @SuppressWarnings("unused") @@ -76,8 +85,6 @@ contextListeners = new ArrayList<ContextListener>(); } - - public void setAppName(String name) { this.name = name; }
--- a/src/org/openjdk/sound/PulseAudioMixer.java Fri Aug 01 12:07:21 2008 -0400 +++ b/src/org/openjdk/sound/PulseAudioMixer.java Fri Aug 01 12:12:03 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/PulseAudioSourceDataLine.java Fri Aug 01 12:07:21 2008 -0400 +++ b/src/org/openjdk/sound/PulseAudioSourceDataLine.java Fri Aug 01 12:12:03 2008 -0400 @@ -19,13 +19,10 @@ public class PulseAudioSourceDataLine implements SourceDataLine { - - private static final int DEFAULT_BUFFER_SIZE = 1000; private String streamName = "Java Stream"; - private List<StreamListener> streamListeners = new ArrayList(); + private List<StreamListener> streamListeners = new ArrayList<StreamListener>(); - private EventLoop eventLoop = null; private boolean isOpen = false; @@ -33,15 +30,21 @@ private AudioFormat format = null; - private ArrayList<LineListener> listeners; + private List<LineListener> listeners; + /* + * When moving from 32bit platform to 64 bit platform, these variables that + * hold pointers will need their sizes changed + * + */ @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_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 length); + private native void native_write(byte[] data,int offset, int length); private native int native_get_writable_size(); @@ -49,18 +52,20 @@ private native int native_flush(); + private native void native_start(); - + private native void native_pause(); private native void native_resume(); + private native int native_drain(); private native void native_close(); - /*static { + static { try { String library = new java.io.File(".").getCanonicalPath() + java.io.File.separatorChar + "lib" @@ -71,10 +76,11 @@ } catch (IOException e) { assert ("Loading failed".endsWith("library")); } - }*/ + } public PulseAudioSourceDataLine(EventLoop eventLoop) { this.eventLoop = eventLoop; + this.listeners = new ArrayList<LineListener>(); } public void open(AudioFormat format, int bufferSize) @@ -86,9 +92,10 @@ int sampleSize = format.getSampleSizeInBits(); String encoding = format.getEncoding().toString(); boolean bigEndian = format.isBigEndian(); - + synchronized (eventLoop.threadLock) { - native_open(eventLoop.getContextPointer(), streamName, encoding, rate, sampleSize, channels, bigEndian, bufferSize); + native_open(eventLoop.getContextPointer(), streamName, encoding, + rate, sampleSize, channels, bigEndian, bufferSize); } } @@ -100,30 +107,31 @@ public void open() throws LineUnavailableException { format = new AudioFormat(44100, 16, 2, true, false); open(format, DEFAULT_BUFFER_SIZE); - } - public int write(byte[] data, int off, int len) { - byte[] buffer; - int position = off; - int remainingLength = len; + @Override + public int write(byte[] data, int offset, int length) { + + int position = offset; + int remainingLength = length; int availableSize; - // + + int sizeWritten = 0; + while (remainingLength != 0) { synchronized (eventLoop.threadLock) { - availableSize = available(); + availableSize = native_get_writable_size(); if (availableSize < 0) { - //throw new StreamFailed(); + return sizeWritten; } if (availableSize > remainingLength) { availableSize = remainingLength; } - buffer = new byte[availableSize]; - System.arraycopy(data, position, buffer, 0, availableSize); /* write a little bit of the buffer */ - native_write(buffer, buffer.length); + native_write(data, position, availableSize); + sizeWritten += availableSize; position += availableSize; remainingLength -= availableSize; @@ -131,14 +139,14 @@ } // all the data should have been played by now - - + assert (sizeWritten == length); /* * 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; + + return sizeWritten; } public void start() { @@ -176,9 +184,6 @@ - - - /* * for(LineListener l :listeners) { l.update(new LineEvent(this, * LineEvent.Type.START, 0)); } @@ -219,15 +224,13 @@ synchronized (eventLoop.threadLock) { native_close(); } - - + for (LineListener l : this.listeners) { l.update(new LineEvent(this, LineEvent.Type.CLOSE, 0)); } } - public int getBufferSize() { // TODO Auto-generated method stub return 0;
--- a/src/org_openjdk_sound_EventLoop.c Fri Aug 01 12:07:21 2008 -0400 +++ b/src/org_openjdk_sound_EventLoop.c Fri Aug 01 12:12:03 2008 -0400 @@ -1,6 +1,7 @@ #include <pulse/pulseaudio.h> #include "org_openjdk_sound_EventLoop.h" +#include "jni-common.h" const int PA_ITERATE_BLOCK = 1; const int PA_ITERATE_NOBLOCK = 0; @@ -10,7 +11,7 @@ jobject obj; } java_context_t; -java_context_t* java_context = NULL; +static java_context_t* java_context = NULL; JNIEnv* pulse_thread_env = NULL; @@ -98,12 +99,8 @@ pa_context_connect(context, NULL, 0, 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); - + setJavaIntField(env, obj, "mainloopPointer", (int) mainloop); + setJavaIntField(env, obj, "contextPointer", (int) context); printf("native_setup() returning\n"); return;
--- a/src/org_openjdk_sound_PulseAudioMixer.c Fri Aug 01 12:07:21 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 12:07:21 2008 -0400 +++ b/src/org_openjdk_sound_PulseAudioSourceDataLine.c Fri Aug 01 12:12:03 2008 -0400 @@ -3,24 +3,9 @@ #include <fcntl.h> #include <jni.h> #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); - //CHECK No DeleteLocalReference Method? - //(*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; -} +#include "jni-common.h" typedef struct java_context_t { @@ -28,6 +13,7 @@ jobject obj; } java_context_t; +static java_context_t* java_context; /* defined in EventLoop.c */ extern JNIEnv* pulse_thread_env; @@ -48,7 +34,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) { @@ -84,8 +70,6 @@ } - - /* * Class: org_openjdk_sound_PulseAudioSourceDataLine * Method: native_open @@ -94,46 +78,58 @@ JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1open (JNIEnv* env, jobject obj, jint contextPointer, jstring name, jstring encodingString, jfloat rate, jint size, jint channels, jboolean bigEndian, jint bufferSize) { + //TODO: Need to deal with the buffer size. Currently ignored + + printf("entering native_open\n"); java_context_t* java_context = malloc(sizeof(java_context)); java_context->env = env; -; java_context->obj = (*env)->NewGlobalRef(env, obj); -; - - 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"); - //TO DO: Invalid format :throw Exception; - } - - sample_spec.rate = rate; - sample_spec.channels = channels; + + pa_context* context = (pa_context*) contextPointer; + assert(context != NULL); + + pa_sample_spec sample_spec; + + const char *encoding = (*env)->GetStringUTFChars(env, encodingString, NULL); - - pa_stream *stream = pa_stream_new(contextPointer, "default stream", &sample_spec, 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; + } - pa_stream_set_state_callback(stream, stream_state_change_callback, java_context); - + sample_spec.rate = rate; + sample_spec.channels = channels; + /* 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); - setJavaIntField(env, obj, stream, "streamPointer"); + pa_stream_set_state_callback(stream, stream_state_change_callback, java_context); + + setJavaIntField(env, obj, "streamPointer", (int) stream); + printf("returning from native_open\n"); + } /* @@ -142,14 +138,19 @@ * Signature: ([BII)V */ JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1write -(JNIEnv* env, jobject obj, jbyteArray data, jint data_length) { +(JNIEnv* env, jobject obj, jbyteArray data, jint offset, jint data_length) { - pa_stream *stream = getJavaIntField(env, obj, "streamPointer"); + 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); + data_buffer +=offset; pa_stream_write(stream, data_buffer, data_length, NULL, 0, PA_SEEK_RELATIVE); (*env)->ReleaseByteArrayElements(env, data, data_buffer, 0); - + } /* @@ -166,7 +167,6 @@ } - /* * Class: org_openjdk_sound_PulseAudioSourceDataLine * Method: native_flush @@ -198,11 +198,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 = (pa_stream*)getJavaIntField(env, obj, "streamPointer"); + pa_stream_connect_playback(stream, NULL, NULL, 0, NULL, NULL); }
--- a/src/org_openjdk_sound_PulseAudioSourceDataLine.c_ORIGINAL Fri Aug 01 12:07:21 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,260 +0,0 @@ -#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 Fri Aug 01 12:07:21 2008 -0400 +++ b/src/org_openjdk_sound_PulseAudioSourceDataLine.h Fri Aug 01 12:12:03 2008 -0400 @@ -20,10 +20,10 @@ /* * Class: org_openjdk_sound_PulseAudioSourceDataLine * Method: native_write - * Signature: ([BI)V + * Signature: ([BII)V */ JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1write - (JNIEnv *, jobject, jbyteArray, jint); + (JNIEnv *, jobject, jbyteArray, jint, jint); /* * Class: org_openjdk_sound_PulseAudioSourceDataLine
--- a/src/org_openjdk_sound_PulseAudioStreamVolumeControl.c Fri Aug 01 12:07:21 2008 -0400 +++ b/src/org_openjdk_sound_PulseAudioStreamVolumeControl.c Fri Aug 01 12:12:03 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 12:07:21 2008 -0400 +++ b/src/org_openjdk_sound_PulseAudioTargetDataLine.c Fri Aug 01 12:12:03 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); +} - - - -