Mercurial > hg > pulseaudio
changeset 23:9ce846af2c4d
for debugging
committer: Ioana Ivan <iivan@redhat.com>
author | Ioana Ivan <iivan@redhat.com> |
---|---|
date | Tue, 29 Jul 2008 11:29:44 -0400 |
parents | 68e6a71e97f3 |
children | 03101556665f |
files | src/org_openjdk_sound_PulseAudioSourceDataLine.c |
diffstat | 1 files changed, 260 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org_openjdk_sound_PulseAudioSourceDataLine.c Tue Jul 29 11:29:44 2008 -0400 @@ -0,0 +1,260 @@ +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <jni.h> +#include <pulse/pulseaudio.h> +#include "org_openjdk_sound_PulseAudioSourceDataLine.h" + +void setJavaLongField(JNIEnv *env, jobject obj, void *ptr, char *fieldName) { + jclass cls = (*env)->GetObjectClass(env, obj); + jlong value = (long) ptr; + jfieldID fid =(*env)->GetFieldID(env, cls, fieldName, "J"); + (*env)->SetLongField(env, obj, fid, value); + //CHECK No DeleteLocalReference Method? + //(*env)->DeleteLocalReference(cls); +} + +void *getJavaLongField(JNIEnv *env, jobject obj, char *fieldName) { +jclass cls = (*env)->GetObjectClass(env, obj); + jfieldID fid = (*env)->GetFieldID(env, cls, fieldName, "J"); + jlong value = (*env)->GetLongField(env, obj, fid); + //(*env)->DeleteLocalReference(cls); + return (void *) value; +} + + + +static void stream_write_cb(pa_stream* stream, size_t length, void* userdata) { + pa_threaded_mainloop *mainloop = userdata; + pa_threaded_mainloop_signal(mainloop,0); +} + +static void stream_operation_complete_cb(pa_stream* stream, int success, void* userdata) { + pa_threaded_mainloop *mainloop = userdata; + pa_threaded_mainloop_signal(mainloop,0); +} + + + +static void stream_state_cb(pa_stream* stream, void* userdata) { + assert(stream); + pa_threaded_mainloop *mainloop = userdata; + printf("stream state changed to %d\n", pa_stream_get_state(stream)); + switch (pa_stream_get_state(stream)) { + case PA_STREAM_READY: + case PA_STREAM_FAILED: + pa_threaded_mainloop_signal(mainloop, 0); + break; + case PA_STREAM_TERMINATED: + printf("STREAM DISCONNECTING\n"); + pa_threaded_mainloop_signal(mainloop, 0); + break; + + default: + /* do nothing */ + break; + } + } + + + + +JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_openStream + (JNIEnv * env, jobject obj, jstring string, jfloat rate, jint size, jint channels, jboolean bigEndian, jint bufferSize){ + + //TO DO: Need to deal with the buffer size. Currently ignored + + pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); + pa_context *context = getJavaLongField(env, obj, "contextPointer"); + + + pa_sample_spec sample_spec; + + char *encoding = (*env)->GetStringUTFChars(env, string, NULL); + + if( (strcmp(encoding, "PCM_UNSIGNED") == 0) && (size == 8)) { + sample_spec.format = PA_SAMPLE_U8; + } else if( (strcmp(encoding, "ALAW") == 0) && (size == 8)) { + sample_spec.format = PA_SAMPLE_ALAW; + } else if( (strcmp(encoding, "ULAW") == 0) && (size == 8)) { + sample_spec.format = PA_SAMPLE_ULAW; + } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 16) && (bigEndian == 1)) { + sample_spec.format = PA_SAMPLE_S16BE; + } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 16) && (bigEndian == 0)) { + sample_spec.format = PA_SAMPLE_S16LE; + } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 32) && (bigEndian == 1)) { + sample_spec.format = PA_SAMPLE_S32BE; + } else if ( (strcmp(encoding, "PCM_SIGNED") == 0) && (size == 32) && (bigEndian == 0)) { + sample_spec.format = PA_SAMPLE_S32LE; + } else { + printf("error in open"); + //TO DO: Invalid format :throw Exception; + } + + sample_spec.rate = rate; + sample_spec.channels = channels; + + pa_threaded_mainloop_lock(mainloop); + + pa_stream *stream = pa_stream_new(context, "default stream", &sample_spec, NULL); + + pa_stream_set_state_callback(stream, stream_state_cb, mainloop); + pa_stream_set_write_callback(stream, stream_write_cb, mainloop); + + + pa_threaded_mainloop_unlock(mainloop); + + + setJavaLongField(env, obj, stream, "streamPointer"); + return; + +unlock_and_fail: + pa_threaded_mainloop_unlock(mainloop); + +fail: + return; +} + +JNIEXPORT void JNICALL +Java_org_openjdk_sound_PulseAudioSourceDataLine_startStream(JNIEnv *env, jobject obj) { + printf("start called\n"); + pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); + pa_stream *stream = getJavaLongField(env, obj, "streamPointer"); + pa_threaded_mainloop_lock(mainloop); + pa_stream_connect_playback(stream, NULL, NULL, 0, NULL, NULL); + pa_threaded_mainloop_wait(mainloop); + if ( pa_stream_get_state(stream) != PA_STREAM_READY ) { + printf("stream initialization failed\n"); + } + pa_threaded_mainloop_unlock(mainloop); +} + +JNIEXPORT void Java_org_openjdk_sound_PulseAudioSourceDataLine_resumeStream(JNIEnv *env, jobject obj) { + pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); + pa_stream *stream = getJavaLongField(env, obj, "streamPointer"); + pa_threaded_mainloop_lock(mainloop); + pa_operation *o = pa_stream_cork(stream, 0, stream_operation_complete_cb, mainloop); + while(pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(mainloop); + } + pa_operation_unref(o); + pa_threaded_mainloop_unlock(mainloop); + +} + +JNIEXPORT void Java_org_openjdk_sound_PulseAudioSourceDataLine__pauseStream(JNIEnv *env, jobject obj) { + pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); + pa_stream *stream = getJavaLongField(env, obj, "streamPointer"); + pa_threaded_mainloop_lock(mainloop); + pa_operation *o = pa_stream_cork(stream, 1, stream_operation_complete_cb, mainloop); + while(pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(mainloop); + } + pa_operation_unref(o); + pa_threaded_mainloop_unlock(mainloop); +} + + + +JNIEXPORT void JNICALL +Java_org_openjdk_sound_PulseAudioSourceDataLine_writeToStream(JNIEnv *env, jobject obj, jbyteArray data, jint bytesRead, jint indexJava) { + printf("write called\n"); + pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); + pa_stream *stream = getJavaLongField(env, obj, "streamPointer"); + unsigned char *buffer = (*env)->GetByteArrayElements(env, data, NULL); + int length = bytesRead; + int offset = indexJava; + buffer += offset; + + + pa_threaded_mainloop_lock(mainloop); + + while (length > 0) { + + int available_size = pa_stream_writable_size(stream); + while (available_size == 0) { + pa_threaded_mainloop_wait(mainloop); + available_size = pa_stream_writable_size(stream); + } + + if (available_size > length) { + available_size = length; + } + + if (pa_stream_get_state(stream) != PA_STREAM_READY ) { + printf("stream errored!\n"); + goto unlock_and_fail; + } + + pa_stream_write(stream, buffer, available_size, NULL, 0, PA_SEEK_RELATIVE); + printf("written%d\n", available_size); + + + buffer += available_size; + length -= available_size; + + } + + pa_operation_unref(pa_stream_drain(stream, NULL, NULL)); + + pa_threaded_mainloop_unlock(mainloop); + + + return; + +unlock_and_fail: + pa_threaded_mainloop_unlock(mainloop); +fail: + return; + +} + +JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_closeStream + (JNIEnv *env, jobject obj) { + pa_stream *stream = getJavaLongField(env, obj, "streamPointer"); + printf("STREAM POINTER: %d\n", stream); + pa_stream_disconnect(stream); +} + +JNIEXPORT jint JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_available + (JNIEnv *env, jobject obj) { + pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); + pa_stream *stream = getJavaLongField(env, obj, "streamPointer"); + pa_threaded_mainloop_lock(mainloop); + int available = pa_stream_writable_size(stream); + pa_threaded_mainloop_unlock(mainloop); + return available; + } + + +JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_drain + (JNIEnv *env, jobject obj) { + pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); + pa_stream *stream = getJavaLongField(env, obj, "streamPointer"); + pa_threaded_mainloop_lock(mainloop); + pa_operation *o = pa_stream_drain(stream, stream_operation_complete_cb, mainloop); + while(pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(mainloop); + } + pa_operation_unref(o); + pa_threaded_mainloop_unlock(mainloop); + } + +JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_flush + (JNIEnv *env, jobject obj) { + pa_threaded_mainloop *mainloop = getJavaLongField (env, obj, "mainLoopPointer"); + pa_stream *stream = getJavaLongField(env, obj, "streamPointer"); + pa_threaded_mainloop_lock(mainloop); + pa_operation *o = pa_stream_flush(stream, stream_operation_complete_cb, mainloop); + while(pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(mainloop); + } + pa_operation_unref(o); + pa_threaded_mainloop_unlock(mainloop); + } + + + + + +