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