Mercurial > hg > pulseaudio
changeset 30:f05acd4ee58b
merging changes
committer: Omair Majid <omajid@redhat.com>
author | Omair Majid <omajid@redhat.com> |
---|---|
date | Fri, 01 Aug 2008 11:22:31 -0400 |
parents | b9836224602b (current diff) dbffaa5c4944 (diff) |
children | 70d51e08abbb |
files | src/org/openjdk/sound/PulseAudioSourceDataLine.java src/org_openjdk_sound_PulseAudioSourceDataLine.c |
diffstat | 5 files changed, 177 insertions(+), 54 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jni-common.c Fri Aug 01 11:22:31 2008 -0400 @@ -0,0 +1,4 @@ +#include "jni-common.h" + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jni-common.h Fri Aug 01 11:22:31 2008 -0400 @@ -0,0 +1,15 @@ +#ifndef _JNI_COMMON_H +#define _JNI_COMMON_H + + +/* + * This file contains some commonly used functions + * + */ + + + + + + +#endif \ No newline at end of file
--- a/src/org/openjdk/sound/EventLoop.java Fri Aug 01 10:59:19 2008 -0400 +++ b/src/org/openjdk/sound/EventLoop.java Fri Aug 01 11:22:31 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/PulseAudioSourceDataLine.java Fri Aug 01 10:59:19 2008 -0400 +++ b/src/org/openjdk/sound/PulseAudioSourceDataLine.java Fri Aug 01 11:22:31 2008 -0400 @@ -18,13 +18,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 EventLoop eventLoop = null; private boolean isOpen = false; @@ -34,30 +31,36 @@ private ArrayList<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 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 { + static { try { String library = new java.io.File(".").getCanonicalPath() + java.io.File.separatorChar + "lib" @@ -68,7 +71,7 @@ } catch (IOException e) { assert ("Loading failed".endsWith("library")); } - }*/ + } public PulseAudioSourceDataLine(EventLoop eventLoop) { this.eventLoop = eventLoop; @@ -83,9 +86,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); } } @@ -97,22 +101,42 @@ 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) { - // FIXME - - - synchronized (eventLoop.threadLock) { - native_write(data, off, 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 = native_get_writable_size(); + if (availableSize < 0) { + return sizeWritten; + } + if (availableSize > remainingLength) { + availableSize = remainingLength; + } + /* write a little bit of the buffer */ + native_write(data, position, availableSize); + + sizeWritten += availableSize; + position += availableSize; + remainingLength -= availableSize; + + } } - /* - * 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; + // all the data should have been played by now + assert (sizeWritten == length); + + return sizeWritten; + } public void start() { @@ -189,15 +213,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_PulseAudioSourceDataLine.c Fri Aug 01 10:59:19 2008 -0400 +++ b/src/org_openjdk_sound_PulseAudioSourceDataLine.c Fri Aug 01 11:22:31 2008 -0400 @@ -10,15 +10,14 @@ 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); + (*env)->DeleteLocalReference(cls); } void *getJavaIntField(JNIEnv *env, jobject obj, char *fieldName) { -jclass cls = (*env)->GetObjectClass(env, obj); + jclass cls = (*env)->GetObjectClass(env, obj); jfieldID fid = (*env)->GetFieldID(env, cls, fieldName, "I"); jlong value = (*env)->GetIntField(env, obj, fid); - //(*env)->DeleteLocalReference(cls); + (*env)->DeleteLocalReference(cls); return (void *) value; } @@ -86,6 +85,66 @@ +typedef struct java_context_t { + JNIEnv* env; + jobject obj; +} java_context_t; + + +/* defined in EventLoop.c */ +extern JNIEnv* pulse_thread_env; + + + +static void stream_state_change_callback(pa_stream* stream, void* userdata) { + assert(stream); + assert(userdata); + + printf("entering stream_state_change_callback\n"); + + java_context_t* java_context = (java_context_t*)userdata; + JNIEnv* env; + + /* needed so we can create a stream from another thread + */ + if (pa_stream_get_state(stream) == PA_STREAM_CREATING) { + printf("java thread\n"); + env = java_context->env; + } else { + env = pulse_thread_env; + } + + jobject obj = java_context->obj; + + printf("stream state changed to %d\n", pa_stream_get_state(stream)); + + /* Call the 'update' method in java + * to handle all java-side events + */ + jclass cls = (*env)->GetObjectClass(env, obj); + if (cls == NULL) { + printf("unable to get class of object"); + return; + } + jmethodID mid = (*env)->GetMethodID(env, cls, "update", "(I)V"); + if (mid == NULL) { + printf("unable to get callback method\n"); + return; + + } + printf("calling update on java\n"); + (*env)->CallVoidMethod(env, obj, mid, pa_stream_get_state(stream)); + + printf("returning form stream_state_change_callback\n"); + return; + +} + + + + + + /* * Class: org_openjdk_sound_PulseAudioSourceDataLine * Method: native_open @@ -94,12 +153,16 @@ 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_context* context = (pa_context*) contextPointer; + assert(context != NULL); + pa_sample_spec sample_spec; char *encoding = (*env)->GetStringUTFChars(env, encodingString, NULL); @@ -120,20 +183,28 @@ sample_spec.format = PA_SAMPLE_S32LE; } else { printf("error in open"); - //TO DO: Invalid format :throw Exception; + //TODO: Invalid format :throw Exception; } sample_spec.rate = rate; sample_spec.channels = channels; - - pa_stream *stream = pa_stream_new(contextPointer, "default stream", &sample_spec, NULL); + /* 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); pa_stream_set_state_callback(stream, stream_state_change_callback, java_context); - + setJavaIntField(env, obj, stream, "streamPointer"); + printf("returning from native_open\n"); - setJavaIntField(env, obj, stream, "streamPointer"); } /* @@ -142,14 +213,18 @@ * Signature: ([BII)V */ JNIEXPORT void JNICALL Java_org_openjdk_sound_PulseAudioSourceDataLine_native_1write -(JNIEnv* env, jobject obj, jbyteArray arr, jint int1, jint int2) { +(JNIEnv* env, jobject obj, jbyteArray buffer, jint offset, jint length) { -// 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); + 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); + + pa_stream_write(stream, data_buffer, data_length, NULL, 0, PA_SEEK_RELATIVE); + (*env)->ReleaseByteArrayElements(env, data, data_buffer, 0); + } /* @@ -159,12 +234,12 @@ */ 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); - + + // jfieldID fid = (*env)->GetIntField + // + // pa_stream* stream = (pa_stream*)streamPointer; + // return pa_stream_writable_size(stream); + } /*