Mercurial > hg > pulseaudio
changeset 28:dbffaa5c4944
its coming along
committer: Omair Majid <omajid@redhat.com>
author | Omair Majid <omajid@redhat.com> |
---|---|
date | Fri, 01 Aug 2008 11:03:52 -0400 |
parents | f1a1eaa0f610 |
children | f05acd4ee58b |
files | src/jni-common.c src/jni-common.h src/org/openjdk/sound/EventLoop.java src/org/openjdk/sound/PulseAudioSourceDataLine.java src/org_openjdk_sound_PulseAudioSourceDataLine.c |
diffstat | 5 files changed, 224 insertions(+), 51 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:03:52 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:03:52 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 Thu Jul 31 17:29:47 2008 -0400 +++ b/src/org/openjdk/sound/EventLoop.java Fri Aug 01 11:03:52 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 Thu Jul 31 17:29:47 2008 -0400 +++ b/src/org/openjdk/sound/PulseAudioSourceDataLine.java Fri Aug 01 11:03:52 2008 -0400 @@ -15,43 +15,46 @@ public class PulseAudioSourceDataLine implements SourceDataLine { - - private static final int DEFAULT_BUFFER_SIZE = 1000; private String streamName = "Java Stream"; - + private EventLoop eventLoop = null; private boolean isOpen = false; private boolean isPaused = false; - private final AudioFormat format = null; - + private final AudioFormat lineFormat = null; + 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 { try { String library = new java.io.File(".").getCanonicalPath() @@ -78,9 +81,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); } } @@ -90,30 +94,51 @@ } public void open() throws LineUnavailableException { -// format = new AudioFormat(Encoding.PCM_SIGNED, 44100, 16, 2, ); - -// synchronized (eventLoop.threadLock) { -// openStream("PCM_SIGNED", 44100, 16, 2, false, DEFAULT_BUFFER_SIZE); -// -// } - + // format = new AudioFormat(Encoding.PCM_SIGNED, 44100, 16, 2, ); + + // synchronized (eventLoop.threadLock) { + // openStream("PCM_SIGNED", 44100, 16, 2, false, DEFAULT_BUFFER_SIZE); + // + // } + open(null); - + } - 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() { @@ -156,15 +181,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 Thu Jul 31 17:29:47 2008 -0400 +++ b/src/org_openjdk_sound_PulseAudioSourceDataLine.c Fri Aug 01 11:03:52 2008 -0400 @@ -2,13 +2,133 @@ #include <pulse/pulseaudio.h> +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 * 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) { +(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"); + + 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; + + pa_sample_spec sample_spec; + + const 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"); + (*env)->Throw + } + + 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); + + pa_stream_set_state_callback(stream, stream_state_change_callback, java_context); + + pa_stream_connect_playback(stream, NULL, NULL, 0, NULL, NULL); + + 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"); } @@ -18,14 +138,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); + } /* @@ -35,12 +159,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); + } /*