diff --git a/lib/native/linux-64/libjportaudio.so b/lib/native/linux-64/libjportaudio.so index be77ce82f..8ee9d7166 100755 Binary files a/lib/native/linux-64/libjportaudio.so and b/lib/native/linux-64/libjportaudio.so differ diff --git a/lib/native/linux/libjportaudio.so b/lib/native/linux/libjportaudio.so index 71369327e..628200ec5 100755 Binary files a/lib/native/linux/libjportaudio.so and b/lib/native/linux/libjportaudio.so differ diff --git a/lib/native/mac/libjportaudio.jnilib b/lib/native/mac/libjportaudio.jnilib index efb66be39..b83be4d4c 100755 Binary files a/lib/native/mac/libjportaudio.jnilib and b/lib/native/mac/libjportaudio.jnilib differ diff --git a/lib/native/windows/jportaudio.dll b/lib/native/windows/jportaudio.dll index 1bbf30e95..dc0e1124e 100644 Binary files a/lib/native/windows/jportaudio.dll and b/lib/native/windows/jportaudio.dll differ diff --git a/src/native/portaudio/Makefile b/src/native/portaudio/Makefile index bff03817d..a2d238bf6 100644 --- a/src/native/portaudio/Makefile +++ b/src/native/portaudio/Makefile @@ -14,5 +14,5 @@ CPPFLAGS=-DJNI_IMPLEMENTATION \ LDFLAGS=-shared LIBS=-L$(SPEEX_HOME)/libspeex/.libs -L$(PORTAUDIO_HOME)/lib/.libs -static -lportaudio -lspeexdsp -dynamic -lasound -lm -lpthread -$(TARGET): net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio.c net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio.h +$(TARGET): net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h $(CC) $(CPPFLAGS) $< $(LDFLAGS) -o $@ $(LIBS) diff --git a/src/native/portaudio/README b/src/native/portaudio/README index f32a0985e..0bce03069 100644 --- a/src/native/portaudio/README +++ b/src/native/portaudio/README @@ -34,7 +34,7 @@ - Mac OS X CC=gcc -arch i386 -arch ppc -arch x86_64 -mmacosx-version-min=10.3 - LDFLAGS=-shared + LDFLAGS=-dynamiclib LIBS=-L$(PORTAUDIO_HOME)/lib/.libs -framework AudioToolbox -framework AudioUnit -framework CoreAudio -framework Carbon -lpthread -pthread -dynamic -lportaudio -lspeexdsp $ make diff --git a/src/native/portaudio/net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio.c b/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c similarity index 86% rename from src/native/portaudio/net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio.c rename to src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c index 1796b73eb..0e0999f20 100644 --- a/src/native/portaudio/net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio.c +++ b/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c @@ -4,7 +4,7 @@ * Distributable under LGPL license. * See terms of license at gnu.org. */ -#include "net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio.h" +#include "net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h" #include #include @@ -127,7 +127,7 @@ static Buffer* getBuffer(PortAudioStream *st, int time) } JNIEXPORT void JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_setEchoCancelParams +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_setEchoCancelParams (JNIEnv *env, jclass clazz, jlong instream, jlong outstream, jboolean enableDenoise, @@ -169,21 +169,21 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_setEch } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetDefaultInputDevice +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetDefaultInputDevice (JNIEnv *env, jclass clazz) { return Pa_GetDefaultInputDevice(); } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetDefaultOutputDevice +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetDefaultOutputDevice (JNIEnv *env, jclass clazz) { return Pa_GetDefaultOutputDevice(); } JNIEXPORT void JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1CloseStream( +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1CloseStream( JNIEnv *env, jclass clazz, jlong stream) { PortAudioStream *portAudioStream = (PortAudioStream *) stream; @@ -213,7 +213,7 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1Cl } JNIEXPORT void JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1AbortStream +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1AbortStream (JNIEnv *env, jclass clazz, jlong stream) { PaError errorCode = Pa_AbortStream(((PortAudioStream *) stream)->stream); @@ -223,7 +223,7 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1Ab } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetDeviceCount( +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetDeviceCount( JNIEnv *env, jclass clazz) { PaDeviceIndex deviceCount = Pa_GetDeviceCount(); @@ -234,14 +234,14 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1Ge } JNIEXPORT jlong JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetDeviceInfo( +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetDeviceInfo( JNIEnv *env, jclass clazz, jint deviceIndex) { return (jlong) Pa_GetDeviceInfo(deviceIndex); } JNIEXPORT void JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1Initialize( +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1Initialize( JNIEnv *env, jclass clazz) { PaError errorCode = Pa_Initialize(); @@ -251,7 +251,7 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1In } JNIEXPORT jlong JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1OpenStream( +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1OpenStream( JNIEnv *env, jclass clazz, jlong inputParameters, @@ -350,7 +350,7 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1Op } JNIEXPORT void JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1StartStream( +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1StartStream( JNIEnv *env, jclass clazz, jlong stream) { PaError errorCode = Pa_StartStream(((PortAudioStream *) stream)->stream); @@ -360,7 +360,7 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1St } JNIEXPORT void JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1StopStream( +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1StopStream( JNIEnv *env, jclass clazz, jlong stream) { PaError errorCode = Pa_StopStream(((PortAudioStream *) stream)->stream); @@ -370,7 +370,7 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1St } JNIEXPORT void JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1WriteStream( +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1WriteStream( JNIEnv *env, jclass clazz, jlong stream, jbyteArray buffer, jlong frames) { jbyte* data = (*env)->GetByteArrayElements(env, buffer, NULL); @@ -444,7 +444,7 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1Wr } JNIEXPORT void JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1ReadStream +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1ReadStream (JNIEnv *env, jclass clazz, jlong stream, jbyteArray buffer, jlong frames) { jbyte* data = (*env)->GetByteArrayElements(env, buffer, NULL); @@ -557,7 +557,7 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1Re } JNIEXPORT jlong JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetStreamReadAvailable +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetStreamReadAvailable (JNIEnv *env, jclass clazz, jlong stream) { return Pa_GetStreamReadAvailable(((PortAudioStream *) stream)->stream) / @@ -565,21 +565,21 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1Ge } JNIEXPORT jlong JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetStreamWriteAvailable +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetStreamWriteAvailable (JNIEnv *env, jclass clazz, jlong stream) { return Pa_GetStreamWriteAvailable(((PortAudioStream *) stream)->stream); } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetSampleSize +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetSampleSize (JNIEnv *env, jclass clazz, jlong format) { return Pa_GetSampleSize(format); } JNIEXPORT jboolean JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1IsFormatSupported +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1IsFormatSupported (JNIEnv *env, jclass clazz, jlong inputParameters, jlong outputParameters, @@ -595,14 +595,14 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1Is } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getMaxInputChannels( +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getMaxInputChannels( JNIEnv *env, jclass clazz, jlong deviceInfo) { return ((PaDeviceInfo *) deviceInfo)->maxInputChannels; } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getMaxOutputChannels( +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getMaxOutputChannels( JNIEnv *env, jclass clazz, jlong deviceInfo) { return ((PaDeviceInfo *) deviceInfo)->maxOutputChannels; @@ -610,7 +610,7 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDevi JNIEXPORT jstring JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getName( +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getName( JNIEnv *env, jclass clazz, jlong deviceInfo) { const char *name = ((PaDeviceInfo *) deviceInfo)->name; @@ -619,63 +619,63 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDevi } JNIEXPORT jdouble JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultSampleRate +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultSampleRate (JNIEnv *env, jclass clazz, jlong deviceInfo) { return ((PaDeviceInfo *) deviceInfo)->defaultSampleRate; } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getHostApi +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getHostApi (JNIEnv *env, jclass clazz, jlong deviceInfo) { return ((PaDeviceInfo *) deviceInfo)->hostApi; } JNIEXPORT jdouble JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowInputLatency +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowInputLatency (JNIEnv *env, jclass clazz, jlong deviceInfo) { return ((PaDeviceInfo *) deviceInfo)->defaultLowInputLatency; } JNIEXPORT jdouble JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowOutputLatency +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowOutputLatency (JNIEnv *env, jclass clazz, jlong deviceInfo) { return ((PaDeviceInfo *) deviceInfo)->defaultLowOutputLatency; } JNIEXPORT jdouble JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighInputLatency +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighInputLatency (JNIEnv *env, jclass clazz, jlong deviceInfo) { return ((PaDeviceInfo *) deviceInfo)->defaultHighInputLatency; } JNIEXPORT jdouble JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighOutputLatency +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighOutputLatency (JNIEnv *env, jclass clazz, jlong deviceInfo) { return ((PaDeviceInfo *) deviceInfo)->defaultHighOutputLatency; } JNIEXPORT jlong JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetHostApiInfo +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetHostApiInfo (JNIEnv *env , jclass clazz, jint hostApiIndex) { return (jlong) Pa_GetHostApiInfo(hostApiIndex); } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetType +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetType (JNIEnv *env, jclass clazz, jlong hostApi) { return ((PaHostApiInfo *) hostApi)->type; } JNIEXPORT jstring JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetName +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetName (JNIEnv *env, jclass clazz, jlong hostApi) { const char *name = ((PaHostApiInfo *) hostApi)->name; @@ -684,28 +684,28 @@ Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHost } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetDeviceCount +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetDeviceCount (JNIEnv *env, jclass clazz, jlong hostApi) { return ((PaHostApiInfo *) hostApi)->deviceCount; } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetDefaultInputDevice +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetDefaultInputDevice (JNIEnv *env, jclass clazz, jlong hostApi) { return ((PaHostApiInfo *) hostApi)->defaultInputDevice; } JNIEXPORT jint JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetDefaultOutputDevice +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetDefaultOutputDevice (JNIEnv *env, jclass clazz, jlong hostApi) { return ((PaHostApiInfo *) hostApi)->defaultOutputDevice; } JNIEXPORT jlong JNICALL -Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaStreamParameters_1new( +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaStreamParameters_1new( JNIEnv *env, jclass clazz, jint deviceIndex, @@ -738,11 +738,11 @@ PortAudio_fixInputParametersSuggestedLatency( if (deviceInfo) { if(inputParameters->suggestedLatency == - net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_LOW) + net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_LOW) inputParameters->suggestedLatency = deviceInfo->defaultLowInputLatency; else if(inputParameters->suggestedLatency == - net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_HIGH + net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_HIGH || inputParameters->suggestedLatency == 0) inputParameters->suggestedLatency = deviceInfo->defaultHighInputLatency; @@ -762,11 +762,11 @@ PortAudio_fixOutputParametersSuggestedLatency( if (deviceInfo) { if(outputParameters->suggestedLatency == - net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_LOW) + net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_LOW) outputParameters->suggestedLatency = deviceInfo->defaultLowOutputLatency; else if(outputParameters->suggestedLatency == - net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_HIGH + net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_HIGH || outputParameters->suggestedLatency == 0) outputParameters->suggestedLatency = deviceInfo->defaultHighOutputLatency; @@ -795,7 +795,7 @@ PortAudio_throwException(JNIEnv *env, PaError errorCode) = (*env) ->FindClass( env, - "net/java/sip/communicator/impl/neomedia/protocol/portaudio/PortAudioException"); + "net/java/sip/communicator/impl/neomedia/portaudio/PortAudioException"); if (clazz) (*env)->ThrowNew(env, clazz, Pa_GetErrorText(errorCode)); diff --git a/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h b/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h new file mode 100644 index 000000000..18d509908 --- /dev/null +++ b/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h @@ -0,0 +1,309 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class net_java_sip_communicator_impl_neomedia_portaudio_PortAudio */ + +#ifndef _Included_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio +#define _Included_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio +#ifdef __cplusplus +extern "C" { +#endif +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_FRAMES_PER_BUFFER_UNSPECIFIED +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_FRAMES_PER_BUFFER_UNSPECIFIED 0LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT16 +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT16 8LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_FLOAT32 +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_FLOAT32 1LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT32 +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT32 2LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT24 +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT24 4LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT8 +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT8 16LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_UINT8 +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_UINT8 32LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_NO_FLAG +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_NO_FLAG 0LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_CLIP_OFF +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_CLIP_OFF 1LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_DITHER_OFF +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_DITHER_OFF 2LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_NEVER_DROP_INPUT +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_NEVER_DROP_INPUT 4LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_PRIME_OUTPUT_BUFFERS_USING_STREAM_CALLBACK +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_PRIME_OUTPUT_BUFFERS_USING_STREAM_CALLBACK 8LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_PLATFORM_SPECIFIC_FLAGS +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_PLATFORM_SPECIFIC_FLAGS -65536LL +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_UNSEPCIFIED +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_UNSEPCIFIED 0.0 +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_HIGH +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_HIGH -1.0 +#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_LOW +#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_LOW -2.0 +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: setEchoCancelParams + * Signature: (JJZZII)V + */ +JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_setEchoCancelParams + (JNIEnv *, jclass, jlong, jlong, jboolean, jboolean, jint, jint); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_GetDefaultInputDevice + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetDefaultInputDevice + (JNIEnv *, jclass); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_GetDefaultOutputDevice + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetDefaultOutputDevice + (JNIEnv *, jclass); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_CloseStream + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1CloseStream + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_AbortStream + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1AbortStream + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_GetDeviceCount + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetDeviceCount + (JNIEnv *, jclass); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_GetDeviceInfo + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetDeviceInfo + (JNIEnv *, jclass, jint); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_Initialize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1Initialize + (JNIEnv *, jclass); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_OpenStream + * Signature: (JJDJJLnet/java/sip/communicator/impl/neomedia/portaudio/PortAudioStreamCallback;)J + */ +JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1OpenStream + (JNIEnv *, jclass, jlong, jlong, jdouble, jlong, jlong, jobject); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_StartStream + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1StartStream + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_StopStream + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1StopStream + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_WriteStream + * Signature: (J[BJ)V + */ +JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1WriteStream + (JNIEnv *, jclass, jlong, jbyteArray, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_ReadStream + * Signature: (J[BJ)V + */ +JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1ReadStream + (JNIEnv *, jclass, jlong, jbyteArray, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_GetStreamReadAvailable + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetStreamReadAvailable + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_GetStreamWriteAvailable + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetStreamWriteAvailable + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_GetSampleSize + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetSampleSize + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_IsFormatSupported + * Signature: (JJD)Z + */ +JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1IsFormatSupported + (JNIEnv *, jclass, jlong, jlong, jdouble); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaDeviceInfo_getMaxInputChannels + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getMaxInputChannels + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaDeviceInfo_getMaxOutputChannels + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getMaxOutputChannels + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaDeviceInfo_getName + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getName + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaDeviceInfo_getDefaultSampleRate + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultSampleRate + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaDeviceInfo_getHostApi + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getHostApi + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaDeviceInfo_getDefaultLowInputLatency + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowInputLatency + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaDeviceInfo_getDefaultLowOutputLatency + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowOutputLatency + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaDeviceInfo_getDefaultHighInputLatency + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighInputLatency + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaDeviceInfo_getDefaultHighOutputLatency + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighOutputLatency + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: Pa_GetHostApiInfo + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetHostApiInfo + (JNIEnv *, jclass, jint); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaHostApiInfo_GetType + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetType + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaHostApiInfo_GetName + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetName + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaHostApiInfo_GetDeviceCount + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetDeviceCount + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaHostApiInfo_GetDefaultInputDevice + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetDefaultInputDevice + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaHostApiInfo_GetDefaultOutputDevice + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1GetDefaultOutputDevice + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaStreamParameters_new + * Signature: (IIJD)J + */ +JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaStreamParameters_1new + (JNIEnv *, jclass, jint, jint, jlong, jdouble); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/native/portaudio/net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio.h b/src/native/portaudio/net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio.h deleted file mode 100644 index d7c213072..000000000 --- a/src/native/portaudio/net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio.h +++ /dev/null @@ -1,309 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio */ - -#ifndef _Included_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio -#define _Included_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio -#ifdef __cplusplus -extern "C" { -#endif -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_FRAMES_PER_BUFFER_UNSPECIFIED -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_FRAMES_PER_BUFFER_UNSPECIFIED 0LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT16 -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT16 8LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_FLOAT32 -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_FLOAT32 1LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT32 -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT32 2LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT24 -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT24 4LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT8 -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT8 16LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_UINT8 -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_UINT8 32LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_NO_FLAG -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_NO_FLAG 0LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_CLIP_OFF -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_CLIP_OFF 1LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_DITHER_OFF -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_DITHER_OFF 2LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_NEVER_DROP_INPUT -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_NEVER_DROP_INPUT 4LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_PRIME_OUTPUT_BUFFERS_USING_STREAM_CALLBACK -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_PRIME_OUTPUT_BUFFERS_USING_STREAM_CALLBACK 8LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_PLATFORM_SPECIFIC_FLAGS -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_PLATFORM_SPECIFIC_FLAGS -65536LL -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_UNSEPCIFIED -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_UNSEPCIFIED 0.0 -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_HIGH -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_HIGH -1.0 -#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_LOW -#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_LOW -2.0 -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: setEchoCancelParams - * Signature: (JJZZII)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_setEchoCancelParams - (JNIEnv *, jclass, jlong, jlong, jboolean, jboolean, jint, jint); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_GetDefaultInputDevice - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetDefaultInputDevice - (JNIEnv *, jclass); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_GetDefaultOutputDevice - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetDefaultOutputDevice - (JNIEnv *, jclass); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_CloseStream - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1CloseStream - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_AbortStream - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1AbortStream - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_GetDeviceCount - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetDeviceCount - (JNIEnv *, jclass); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_GetDeviceInfo - * Signature: (I)J - */ -JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetDeviceInfo - (JNIEnv *, jclass, jint); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_Initialize - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1Initialize - (JNIEnv *, jclass); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_OpenStream - * Signature: (JJDJJLnet/java/sip/communicator/impl/neomedia/protocol/portaudio/PortAudioStreamCallback;)J - */ -JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1OpenStream - (JNIEnv *, jclass, jlong, jlong, jdouble, jlong, jlong, jobject); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_StartStream - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1StartStream - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_StopStream - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1StopStream - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_WriteStream - * Signature: (J[BJ)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1WriteStream - (JNIEnv *, jclass, jlong, jbyteArray, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_ReadStream - * Signature: (J[BJ)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1ReadStream - (JNIEnv *, jclass, jlong, jbyteArray, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_GetStreamReadAvailable - * Signature: (J)J - */ -JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetStreamReadAvailable - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_GetStreamWriteAvailable - * Signature: (J)J - */ -JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetStreamWriteAvailable - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_GetSampleSize - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetSampleSize - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_IsFormatSupported - * Signature: (JJD)Z - */ -JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1IsFormatSupported - (JNIEnv *, jclass, jlong, jlong, jdouble); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaDeviceInfo_getMaxInputChannels - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getMaxInputChannels - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaDeviceInfo_getMaxOutputChannels - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getMaxOutputChannels - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaDeviceInfo_getName - * Signature: (J)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getName - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaDeviceInfo_getDefaultSampleRate - * Signature: (J)D - */ -JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultSampleRate - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaDeviceInfo_getHostApi - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getHostApi - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaDeviceInfo_getDefaultLowInputLatency - * Signature: (J)D - */ -JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowInputLatency - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaDeviceInfo_getDefaultLowOutputLatency - * Signature: (J)D - */ -JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowOutputLatency - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaDeviceInfo_getDefaultHighInputLatency - * Signature: (J)D - */ -JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighInputLatency - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaDeviceInfo_getDefaultHighOutputLatency - * Signature: (J)D - */ -JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighOutputLatency - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: Pa_GetHostApiInfo - * Signature: (I)J - */ -JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetHostApiInfo - (JNIEnv *, jclass, jint); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaHostApiInfo_GetType - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetType - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaHostApiInfo_GetName - * Signature: (J)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetName - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaHostApiInfo_GetDeviceCount - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetDeviceCount - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaHostApiInfo_GetDefaultInputDevice - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetDefaultInputDevice - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaHostApiInfo_GetDefaultOutputDevice - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetDefaultOutputDevice - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio - * Method: PaStreamParameters_new - * Signature: (IIJD)J - */ -JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaStreamParameters_1new - (JNIEnv *, jclass, jint, jint, jlong, jdouble); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/net/java/sip/communicator/impl/neomedia/codec/EncodingConfiguration.java b/src/net/java/sip/communicator/impl/neomedia/codec/EncodingConfiguration.java index 85b182bef..0f2641359 100644 --- a/src/net/java/sip/communicator/impl/neomedia/codec/EncodingConfiguration.java +++ b/src/net/java/sip/communicator/impl/neomedia/codec/EncodingConfiguration.java @@ -79,8 +79,8 @@ public class EncodingConfiguration * Custom Packages provided by Sip-Communicator */ private static final String[] CUSTOM_PACKAGES = new String[] - { // datasource for low latency ALSA input - "net.java.sip.communicator.impl", "net.sf.fmj" }; + { // datasource for low latency PortAudio or ALSA input + "net.java.sip.communicator.impl.neomedia.jmfext", "net.sf.fmj" }; /** * The Comparator which sorts the sets according to the settings in diff --git a/src/net/java/sip/communicator/impl/neomedia/codec/audio/alaw/JavaEncoder.java b/src/net/java/sip/communicator/impl/neomedia/codec/audio/alaw/JavaEncoder.java index 83d31abb4..1f8e13d6b 100644 --- a/src/net/java/sip/communicator/impl/neomedia/codec/audio/alaw/JavaEncoder.java +++ b/src/net/java/sip/communicator/impl/neomedia/codec/audio/alaw/JavaEncoder.java @@ -129,6 +129,11 @@ public int process(Buffer inputBuffer, Buffer outputBuffer) initConverter( (AudioFormat) newFormat); } + if (inputBuffer.getLength() == 0) + { + return OUTPUT_BUFFER_NOT_FILLED; + } + int outLength = calculateOutputSize(inputBuffer.getLength()); byte[] inpData = (byte[]) inputBuffer.getData(); diff --git a/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java b/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java index 81357c2be..bb74d5001 100644 --- a/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java +++ b/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java @@ -11,7 +11,7 @@ import javax.media.*; import javax.media.format.*; -import net.java.sip.communicator.impl.neomedia.protocol.portaudio.*; +import net.java.sip.communicator.impl.neomedia.portaudio.*; import net.java.sip.communicator.impl.neomedia.*; import net.java.sip.communicator.service.configuration.*; import net.java.sip.communicator.util.*; @@ -691,8 +691,9 @@ else if(name.equals(AUDIO_SYSTEM_PORTAUDIO)) protected static void initPortAudioRenderer() { PlugInManager.addPlugIn( - "net.java.sip.communicator.impl.neomedia.renderer.audio.PortAudioRenderer", - net.java.sip.communicator.impl.neomedia.renderer.audio. + "net.java.sip.communicator.impl.neomedia.jmfext" + + ".media.renderer.audio.PortAudioRenderer", + net.java.sip.communicator.impl.neomedia.jmfext.media.renderer.audio. PortAudioRenderer.supportedInputFormats, null, PlugInManager.RENDERER); @@ -714,7 +715,8 @@ private void removeJavaSoundRenderer() private void removePortAudioRenderer() { PlugInManager.removePlugIn( - "net.java.sip.communicator.impl.neomedia.renderer.audio.PortAudioRenderer", + "net.java.sip.communicator.impl.neomedia.jmfext" + + ".media.renderer.audio.PortAudioRenderer", PlugInManager.RENDERER); } @@ -751,7 +753,7 @@ private void setDeviceToRenderer(CaptureDeviceInfo devInfo) try { - net.java.sip.communicator.impl.neomedia.renderer.audio. + net.java.sip.communicator.impl.neomedia.jmfext.media.renderer.audio. PortAudioRenderer.setDevice(devInfo.getLocator()); } catch (Exception e) diff --git a/src/net/java/sip/communicator/impl/neomedia/device/PortAudioAuto.java b/src/net/java/sip/communicator/impl/neomedia/device/PortAudioAuto.java index 7dd83e952..b33ad5275 100644 --- a/src/net/java/sip/communicator/impl/neomedia/device/PortAudioAuto.java +++ b/src/net/java/sip/communicator/impl/neomedia/device/PortAudioAuto.java @@ -10,7 +10,8 @@ import javax.media.*; -import net.java.sip.communicator.impl.neomedia.protocol.portaudio.*; +import net.java.sip.communicator.impl.neomedia.portaudio.*; +import net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio.*; import net.java.sip.communicator.util.*; import com.sun.media.util.*; diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/alsa/AlsaStream.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/alsa/AlsaStream.java new file mode 100644 index 000000000..f34b7928d --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/alsa/AlsaStream.java @@ -0,0 +1,219 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.alsa; + +import javax.media.*; +import javax.media.format.*; +import javax.media.protocol.*; +import java.io.IOException; + +/** + * low-latency ALSA access through JNI wrapper + * + * @author Jean Lorchat + */ +public class AlsaStream + implements PushBufferStream, Runnable +{ + protected ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW); + protected int maxDataLength; + protected AudioFormat audioFormat; + protected boolean started; + protected Thread thread; + protected BufferTransferHandler transferHandler; + protected Control [] controls = new Control[0]; + + private native void jni_alsa_init(); + private native void jni_alsa_read(byte [] arr); + private native void jni_alsa_delete(); + + int seqNo = 0; + + /** + * Dynamically loads JNI object. Will fail if non-Linux + * or when libjmf_alsa.so is outside of the LD_LIBRARY_PATH + */ + static { + System.loadLibrary("jmf_alsa"); + } + + /** + * We only provide 8 kbps access to the device for now + * In addition, datablock size is fixed to 160 samples (320 bytes) + * This turns out to be 20ms worth of samples at 8kbps + * Very convenient for ilbc 20ms mode... + */ + public AlsaStream() { + + audioFormat = new AudioFormat(AudioFormat.LINEAR, + 8000.0, + 16, + 1, + AudioFormat.LITTLE_ENDIAN, + AudioFormat.SIGNED, + 16, + Format.NOT_SPECIFIED, + Format.byteArray); + + maxDataLength = 160; + + jni_alsa_init(); + thread = new Thread(this); + } + + /** + * Methods required for SourceStream interface + * + */ + + /** + * We are providing access to raw data + * + */ + public ContentDescriptor getContentDescriptor() { + return cd; + } + + /** + * Come on, we are streaming. Can't guess when the user wants to stop... + * + */ + public long getContentLength() { + return LENGTH_UNKNOWN; + } + + /** + * The stream of happiness never ends, somehow. + * + */ + public boolean endOfStream() { + return false; + } + + /** + * Tell whoever has interest how we are going to send the data + * + */ + public Format getFormat() { + return audioFormat; + } + + /** + * Reads sample data using native call + * + * @param buffer A Buffer with byte array as data, large enough to be + * filled with sample data. If this is not the case, we are going + * to allocate it ourselves anyway and replace the current data. + * + * @throws IOException Native method might throw an exception. + * Well actually that would surprise me because it is not + * implemented, but we love to be future-proof, isn't it ? + */ + public void read(Buffer buffer) throws IOException { + synchronized (this) { + Object outdata = buffer.getData(); + + if (outdata == null || + !(outdata.getClass() == Format.byteArray) || + ((byte[])outdata).length < maxDataLength) { + outdata = new byte[maxDataLength]; + buffer.setData(outdata); + } + + buffer.setFormat(audioFormat); + buffer.setTimeStamp(1000000000 / 8); + jni_alsa_read((byte[])outdata); + buffer.setSequenceNumber(seqNo); + buffer.setLength(maxDataLength); + buffer.setFlags(0); + buffer.setHeader(null); + seqNo++; + } + } + + /** + * Dunno about that piece yet... + * + */ + public void setTransferHandler(BufferTransferHandler transferHandler) { + synchronized (this) { + this.transferHandler = transferHandler; + notifyAll(); + } + } + + /** + * Starts a new thread for the stream operation + * + */ + void start(boolean started) { + synchronized (this) { + this.started = started; + if (started && !thread.isAlive()) { + thread = new Thread(this); + thread.start(); + } + notifyAll(); + } + } + + /** + * Transfer Buffer information through current thread then sleep + * until next data slice is ready. + * + */ + public void run() { + while (started) { + + synchronized (this) { + while (transferHandler == null && started) { + try { + wait(1000); + } catch (InterruptedException ie) { + } + } + } + + if (started && transferHandler != null) { + transferHandler.transferData(this); + try { + Thread.sleep(1); + } catch (InterruptedException ise) { + } + } + + } + } + + + /** + * Gives control information to the caller + * + */ + public Object [] getControls() { + return controls; + } + + /** + * Return required control from the Control[] array + * if exists, that is + */ + public Object getControl(String controlType) { + try { + Class cls = Class.forName(controlType); + Object cs[] = getControls(); + for (int i = 0; i < cs.length; i++) { + if (cls.isInstance(cs[i])) + return cs[i]; + } + return null; + + } catch (Exception e) { + return null; + } + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/alsa/DataSource.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/alsa/DataSource.java new file mode 100644 index 000000000..be97891f7 --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/alsa/DataSource.java @@ -0,0 +1,146 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.alsa; + +import javax.media.Time; +import javax.media.protocol.*; +import java.io.IOException; + +/** + * low-latency ALSA access through JNI wrapper + * + * @author Jean Lorchat + */ +public class DataSource + extends PushBufferDataSource +{ + protected Object [] controls = new Object[0]; + protected boolean started = false; + protected String contentType = "raw"; + protected boolean connected = false; + protected Time duration = DURATION_UNKNOWN; + protected AlsaStream [] streams = null; + protected AlsaStream stream = null; + + public DataSource() { + } + + /** + * Tell we are a raw datasource + * + * @return "raw" + */ + public String getContentType() { + if (!connected){ + System.err.println("Error: DataSource not connected"); + return null; + } + return contentType; + } + + /** + * Connect the datasource + */ + public void connect() throws IOException { + if (connected) + return; + connected = true; + } + + /** + * Disconnect the datasource + */ + public void disconnect() { + try { + if (started) + stop(); + } catch (IOException e) {} + connected = false; + } + + /** + * Start the datasource and the underlying stream + */ + public void start() throws IOException { + if (!connected) + throw new java.lang.Error("DataSource must be connected"); + + if (started) + return; + + started = true; + stream.start(true); + } + + /** + * Stop the datasource and it's underlying stream + */ + public void stop() throws IOException { + + if ((!connected) || (!started)) + return; + + started = false; + stream.start(false); + + } + + /** + * Gives control information to the caller + * + */ + public Object [] getControls() { + return controls; + } + + /** + * Return required control from the Control[] array + * if exists, that is + */ + public Object getControl(String controlType) { + try { + Class cls = Class.forName(controlType); + Object cs[] = getControls(); + for (int i = 0; i < cs.length; i++) { + if (cls.isInstance(cs[i])) + return cs[i]; + } + return null; + + } catch (Exception e) { + return null; + } + } + + /** + * Gives to the caller the duration information of our stream + * Which is, obviously unknown. Better turn on that premonition + * switch again, Mrs Cake. + * + * @return DURATION_UNKNOWN + */ + public Time getDuration() { + return duration; + } + + /** + * Returns an array of PushBufferStream containing all the streams + * i.e. only one in our case : only sound + * + * If no stream actually exists, instanciate one on the fly + * + * @return Array of one stream + */ + public PushBufferStream [] getStreams() { + if (streams == null) { + streams = new AlsaStream[1]; + stream = streams[0] = new AlsaStream(); + } + return streams; + } + +} diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/DSAudioStream.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/DSAudioStream.java new file mode 100644 index 000000000..b84b016bf --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/DSAudioStream.java @@ -0,0 +1,197 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio; + +import net.java.sip.communicator.impl.neomedia.portaudio.*; +import net.java.sip.communicator.impl.neomedia.portaudio.streams.*; + +import java.io.*; + +import javax.media.*; +import javax.media.format.*; +import javax.media.protocol.*; + +/** + * The stream used by jmf, wraps our InputPortAudioStream, which wraps + * the actual PortAudio stream. + * + * @author Damian Minkov + * @author Lubomir Marinov + */ +public class DSAudioStream + implements PullBufferStream +{ + private final static ContentDescriptor cd = + new ContentDescriptor(ContentDescriptor.RAW); + + private Control[] controls = new Control[0]; + + private final int deviceIndex; + + private InputPortAudioStream stream = null; + + private int seqNo = 0; + + /** + * Creates new stream. + * @param locator the locator to extract the device index from it. + */ + public DSAudioStream(MediaLocator locator) + { + this.deviceIndex = PortAudioUtils.getDeviceIndexFromLocator(locator); + } + + /** + * Starts the stream operation + * @throws PortAudioException if fail to start. + */ + void start() + throws PortAudioException + { + if(stream == null) + { + AudioFormat audioFormat = + (AudioFormat)DataSource.getCaptureFormat(); + + stream = PortAudioManager.getInstance().getInputStream(deviceIndex, + audioFormat.getSampleRate(), audioFormat.getChannels()); + } + + stream.start(); + } + + /** + * Stops the stream operation. + * @throws PortAudioException if fail to stop. + */ + void stop() + throws PortAudioException + { + stream.stop(); + stream = null; + } + + /** + * Query if the next read will block. + * @return true if a read will block. + */ + public boolean willReadBlock() + { + return false; + } + + /** + * Block and read a buffer from the stream. + * + * @param buffer the Buffer to read captured media into + * @throws IOException if an error occurs while reading. + */ + public void read(Buffer buffer) + throws IOException + { + if (stream == null) + return; + + try + { + byte[] bytebuff = stream.read(); + + buffer.setTimeStamp(System.nanoTime()); + + buffer.setData(bytebuff); + buffer.setLength(bytebuff.length); + + buffer.setFlags(0); + buffer.setFormat(getFormat()); + buffer.setHeader(null); + + buffer.setSequenceNumber(seqNo); + seqNo++; + } + catch (PortAudioException pae) + { + IOException ioe = new IOException(); + + ioe.initCause(pae); + throw ioe; + } + } + + /** + * Returns the supported format by this stream. + * @return supported formats + */ + public Format getFormat() + { + return DataSource.getCaptureFormat(); + } + + /** + * We are providing access to raw data + * @return RAW content descriptor. + */ + public ContentDescriptor getContentDescriptor() + { + return cd; + } + + /** + * We are streaming. + * @return unknown content length. + */ + public long getContentLength() + { + return LENGTH_UNKNOWN; + } + + /** + * The stream never ends. + * @return true if the end of the stream has been reached. + */ + public boolean endOfStream() + { + return false; + } + + /** + * Gives control information to the caller + * @return no controls currently supported. + */ + public Object[] getControls() + { + return controls; + } + + /** + * Return required control from the Control[] array + * if exists + * + * @param controlType the control class name. + * @return the object that implements the control, or null. + */ + public Object getControl(String controlType) + { + try + { + Class cls = Class.forName(controlType); + Object cs[] = getControls(); + for(int i = 0; i < cs.length; i++) + { + if(cls.isInstance(cs[i])) + { + return cs[i]; + } + } + return null; + + } + catch (Exception e) + { + return null; + } + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/DataSource.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/DataSource.java new file mode 100644 index 000000000..25af0349e --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/DataSource.java @@ -0,0 +1,418 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio; + +import java.io.*; +import java.util.*; + +import javax.media.*; +import javax.media.control.*; +import javax.media.format.*; +import javax.media.protocol.*; + +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.impl.neomedia.portaudio.*; + +/** + * Implements DataSource and CaptureDevice for PortAudio. + * + * @author Damian Minkov + * @author Lubomir Marinov + */ +public class DataSource + extends PullBufferDataSource + implements CaptureDevice +{ + + /** + * The Logger used by the DataSource class and its + * instances for logging output. + */ + private static final Logger logger = Logger.getLogger(DataSource.class); + + private boolean connected = false; + + /** + * The JMF controls (which are likely of type Control) available + * for this DataSource. + */ + private final Object[] controls + = new Object[] + { + new FormatControlImpl() + }; + + private boolean started = false; + + private DSAudioStream[] streams = null; + + private static AudioFormat captureAudioFormat = + new AudioFormat( + AudioFormat.LINEAR, + 8000, + 16, + 1, + AudioFormat.LITTLE_ENDIAN, + AudioFormat.SIGNED, + 16, + Format.NOT_SPECIFIED, + Format.byteArray); + + /** + * Return the formats supported by the datasource. + * + * @return the supported formats. + */ + public static Format getCaptureFormat() + { + return captureAudioFormat; + } + + /** + * Connect the datasource + * @throws IOException if we cannot initialize portaudio. + */ + public void connect() + throws IOException + { + if (connected) + return; + + connected = true; + } + + /** + * Disconnect the datasource + */ + public void disconnect() + { + if (!connected) + return; + + try + { + stop(); + } + catch (IOException ioex) + { + logger + .warn( + "Failed to stop DataSource with locator " + getLocator(), + ioex); + } + + connected = false; + } + + /** + * Gets the CaptureDeviceInfo that describes this + * CaptureDevice. + * + * @return the CaptureDeviceInfo that describes this + * CaptureDevice + */ + public CaptureDeviceInfo getCaptureDeviceInfo() + { + /* + * TODO The implemented search for the CaptureDeviceInfo of this + * CaptureDevice by looking for its MediaLocator is inefficient. + */ + @SuppressWarnings("unchecked") + Vector captureDeviceInfos + = (Vector) + CaptureDeviceManager.getDeviceList(null); + MediaLocator locator = getLocator(); + + for (CaptureDeviceInfo captureDeviceInfo : captureDeviceInfos) + if (captureDeviceInfo.getLocator().equals(locator)) + return captureDeviceInfo; + return null; + } + + /** + * Tell we are a raw datasource + * + * @return "raw" + */ + public String getContentType() + { + return ContentDescriptor.RAW; + } + + /** + * Return required control from the Control[] array + * if exists. + * @param controlType the control we are interested in. + * @return the object that implements the control, or null. + */ + public Object getControl(String controlType) + { + try + { + Class controlClass = Class.forName(controlType); + + for (Object control : getControls()) + if (controlClass.isInstance(control)) + return control; + } + catch (ClassNotFoundException cnfex) + { + logger + .warn( + "Failed to load class of requested controlType " + + controlType, + cnfex); + } + return null; + } + + /** + * Gives control information to the caller + * @return the collection of object controls. + */ + public Object[] getControls() + { + /* + * The field controls represents is private so we cannot directly return + * it. Otherwise, the caller will be able to modify it. + */ + return controls.clone(); + } + + /** + * Gives to the caller the duration information of our stream + * Which is, obviously unknown. + * + * @return DURATION_UNKNOWN + */ + public Time getDuration() + { + return DURATION_UNKNOWN; + } + + /** + * Gets an array of FormatControl instances each one of which can + * be used before {@link #connect()} to get and set the capture + * Format of each one of the capture streams. + * + * @return an array of FormatControl instances each one of which + * can be used before {@link #connect()} to get and set the capture + * Format of each one of the capture streams + */ + public FormatControl[] getFormatControls() + { + List formatControls = new ArrayList(); + + for (Object control : getControls()) + if (control instanceof FormatControl) + formatControls.add((FormatControl) control); + return formatControls.toArray(new FormatControl[formatControls.size()]); + } + + /** + * Returns an array of PullBufferStream containing all the streams + * i.e. only one in our case : only sound. + * + * If no stream actually exists, instantiate one on the fly. + * + * @return Array of one stream + */ + public PullBufferStream[] getStreams() + { + MediaLocator locator = null; + + try + { + if (streams == null) + { + locator = getLocator(); + streams = new DSAudioStream[] { new DSAudioStream(locator) }; + } + } + catch (Exception e) + { + // if we cannot parse desired device we will not open a stream + // so there is no stream returned + streams = new DSAudioStream[0]; + + logger + .error( + "Failed to create DSAudioStream from locator " + locator, + e); + } + + return streams; + } + + /** + * Start the datasource and the underlying stream + * @throws IOException + */ + public void start() + throws IOException + { + if (started) + return; + + if (!connected) + throw new IOException("DataSource must be connected"); + + try + { + streams[0].start(); + } + catch (PortAudioException pae) + { + IOException ioe = new IOException(); + + ioe.initCause(pae); + throw ioe; + } + + started = true; + } + + /** + * Stop the datasource and it's underlying stream + * @throws IOException + */ + public void stop() + throws IOException + { + if (!started) + return; + + try + { + streams[0].stop(); + } + catch (PortAudioException pae) + { + IOException ioe = new IOException(); + + ioe.initCause(pae); + throw ioe; + } + + started = false; + } + + /** + * Implements FormatControl for this DataSource instance. + * At least getting the Format of the DataSource is + * important because, for example, AudioMixer will ask for it. + */ + private class FormatControlImpl + implements FormatControl + { + + /** + * The indicator which determines whether this track is enabled. I don't + * known what it means for DataSource implementations but + * at least the choice of the caller is remembered and reported. + */ + private boolean enabled; + + /** + * Implements {@link Controls#getControlComponent()}. Since + * DataSource does not export any UI, returns null. + * + * @return a Component which represents UI associated with this + * DataSource and this FormatControl if any; + * otherwise, null + */ + public java.awt.Component getControlComponent() + { + // No Component is exported for this DataSource. + return null; + } + + /** + * Implements {@link FormatControl#getFormat()}. + * + * @return the Format of this DataSource + */ + public Format getFormat() + { + return getCaptureFormat(); + } + + /** + * Implements {@link FormatControl#getSupportedFormats()}. + * + * @return an array of Format element type which lists the JMF + * formats supported by this DataSource i.e. the ones in which + * it is able to output + */ + public Format[] getSupportedFormats() + { + return new Format[] { getCaptureFormat() }; + } + + /** + * Implements {@link FormatControl#isEnabled()}. Does not mean anything + * to this DataSource at the time of this writing. + * + * @return true if this track is enabled; otherwise, + * false + */ + public boolean isEnabled() + { + return enabled; + } + + /** + * Implements {@link FormatControl#setEnabled(boolean)}. Does not mean + * anything to this DataSource at the time of this writing. + * + * @param enabled true if this track is to be enabled; + * otherwise, false + */ + public void setEnabled(boolean enabled) + { + this.enabled = enabled; + } + + /** + * Implements {@link FormatControl#setFormat(Format)}. Not supported at + * this time and just returns the currently set format if the specified + * Format is supported and null if it is not + * supported. + * + * @param format the Format in which this DataSource + * is to output + * @return the currently set Format after the attempt to set it + * as the output format of this DataSource if format + * is supported by this DataSource and regardless of whether it + * was actually set; null if format is not supported + * by this DataSource + */ + public Format setFormat(Format format) + { + /* + * Determine whether the specified format is supported by this + * DataSource because we have to return null if it is not supported. + * Or at least that is what I gather from the respective javadoc. + */ + boolean formatIsSupported = false; + + if (format != null) + for (Format supportedFormat : getSupportedFormats()) + if (supportedFormat.matches(format)) + { + formatIsSupported = true; + break; + } + + /* + * We do not actually support setFormat so we have to return the + * currently set format if the specified format is supported. + */ + return (formatIsSupported) ? getFormat() : null; + } + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java new file mode 100644 index 000000000..17f54415f --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java @@ -0,0 +1,250 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.jmfext.media.renderer.audio; + + +import javax.media.*; +import javax.media.format.*; + +import net.java.sip.communicator.impl.neomedia.portaudio.*; +import net.java.sip.communicator.impl.neomedia.portaudio.streams.*; +import net.java.sip.communicator.util.*; + +/** + * Portaudio renderer. + * + * @author Damian Minkov + */ +public class PortAudioRenderer + implements Renderer +{ + private static final Logger logger = + Logger.getLogger(PortAudioRenderer.class); + + private static final String name = "PortAudio Renderer"; + + /** + * The supported input formats. The Inputformats are + * changed after the device is set. + */ + public static Format[] supportedInputFormats = new Format[]{}; + + /** + * The standart supported sample rates. + */ + private static double[] supportedSampleRates = + new double[]{8000, 16000, 22050, 44100, 48000}; + + private Object [] controls = new Object[0]; + private AudioFormat inputFormat; + + private OutputPortAudioStream stream = null; + + boolean started = false; + + private static int deviceIndex = -1; + + /** + * Lists the input formats supported by this Renderer. + * @return An array of Format objects that represent + * the input formats supported by this Renderer. + */ + public Format[] getSupportedInputFormats() + { + return supportedInputFormats; + } + + /** + * Sets the Format of the input data. + * @param format the format to set. + * @return The Format that was set. + */ + public Format setInputFormat(Format format) + { + if(!(format instanceof AudioFormat)) + { + return null; + } + + this.inputFormat = (AudioFormat) format; + + return inputFormat; + } + + /** + * Initiates the rendering process. + * When start is called, the renderer begins rendering + * any data available in its internal buffers. + */ + public void start() + { + try + { + stream.start(); + started = true; + } + catch (PortAudioException e) + { + logger.error("Starting portaudio stream failed", e); + } + } + + /** + * Halts the rendering process. + */ + public synchronized void stop() + { + try + { + started = false; + stream.stop(); + } + catch (PortAudioException e) + { + logger.error("Closing portaudio stream failed", e); + } + } + + /** + * Processes the data and renders it + * to the output device represented by this Renderer. + * @param inputBuffer the input data. + * @return BUFFER_PROCESSED_OK if the processing is successful. + */ + public synchronized int process(Buffer inputBuffer) + { + byte[] buff = new byte[inputBuffer.getLength()]; + System.arraycopy( + (byte[])inputBuffer.getData(), + inputBuffer.getOffset(), + buff, + 0, + buff.length); + + try + { + stream.write(buff); + } + catch (PortAudioException e) + { + logger.error("Error writing to device", e); + } + + return BUFFER_PROCESSED_OK; + } + + /** + * Returns the name of the pluging. + * @return A String that contains the descriptive name of the plug-in. + */ + public String getName() + { + return name; + } + + /** + * Opens the device and stream that we will use to render data. + * @throws ResourceUnavailableException If required resources cannot + * be opened/created. + */ + public void open() + throws ResourceUnavailableException + { + try + { + stream = PortAudioManager.getInstance().getOutputStream(deviceIndex, + inputFormat.getSampleRate(), inputFormat.getChannels()); + } + catch (PortAudioException e) + { + throw new ResourceUnavailableException(e.getMessage()); + } + } + + /** + * Closes the plug-in. + */ + public void close() + { + } + + /** + * Resets the state of the plug-in. + */ + public void reset() + { + } + + /** + * Gives control information to the caller + * @return the collection of object controls. + */ + public Object[] getControls() + { + return controls; + } + + /** + * Return required control from the Control[] array + * if exists. + * @param controlType the control we are interested in. + * @return the object that implements the control, or null. + */ + public Object getControl(String controlType) + { + try + { + Class cls = Class.forName(controlType); + Object cs[] = getControls(); + for(int i = 0; i < cs.length; i++) + { + if(cls.isInstance(cs[i])) + { + return cs[i]; + } + } + return null; + + } + catch (Exception e) + { + return null; + } + } + + /** + * Used to set the device index used by the renderer common for all + * instances of it. Change the format corresponding the device which + * will be used. + * @param locator the locator containing the device index. + */ + public static void setDevice(MediaLocator locator) + { + deviceIndex = PortAudioUtils.getDeviceIndexFromLocator(locator); + + int outputChannels = 1; + + supportedInputFormats = new Format[supportedSampleRates.length]; + + for(int i = 0; i < supportedSampleRates.length; i++) + { + double sampleRate = supportedSampleRates[i]; + + supportedInputFormats[i] = + new AudioFormat( + AudioFormat.LINEAR, + sampleRate, + 16, + outputChannels, + AudioFormat.LITTLE_ENDIAN, + AudioFormat.SIGNED, + 16, + Format.NOT_SPECIFIED, + Format.byteArray); + } + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/notify/PortAudioClipImpl.java b/src/net/java/sip/communicator/impl/neomedia/notify/PortAudioClipImpl.java index ea6eba33d..0a49f23f1 100644 --- a/src/net/java/sip/communicator/impl/neomedia/notify/PortAudioClipImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/notify/PortAudioClipImpl.java @@ -11,8 +11,8 @@ import javax.sound.sampled.*; -import net.java.sip.communicator.impl.neomedia.protocol.portaudio.*; -import net.java.sip.communicator.impl.neomedia.protocol.portaudio.streams.*; +import net.java.sip.communicator.impl.neomedia.portaudio.*; +import net.java.sip.communicator.impl.neomedia.portaudio.streams.*; import net.java.sip.communicator.util.*; /** diff --git a/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudio.java b/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudio.java new file mode 100644 index 000000000..861ad2339 --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudio.java @@ -0,0 +1,479 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.portaudio; + +/** + * PortAudio functions. + * @author Lubomir Marinov + */ +public final class PortAudio +{ + static + { + System.loadLibrary("jportaudio"); + } + + /** + * Can be passed as the framesPerBuffer parameter to + * Pa_OpenStream() or Pa_OpenDefaultStream() to indicate that the stream + * callback will accept buffers of any size. + */ + public static final long FRAMES_PER_BUFFER_UNSPECIFIED = 0; + + /** + * A type used to specify one or more sample formats. + * The standard format paInt16. + */ + public static final long SAMPLE_FORMAT_INT16 = 0x00000008; + + /** + * A type used to specify one or more sample formats. + * The format paFloat32. + */ + public static final long SAMPLE_FORMAT_FLOAT32 = 0x00000001; + + /** + * A type used to specify one or more sample formats. + * The format paInt32. + */ + public static final long SAMPLE_FORMAT_INT32 = 0x00000002; + + /** + * A type used to specify one or more sample formats. + * The format paInt24. + */ + public static final long SAMPLE_FORMAT_INT24 = 0x00000004; + + /** + * A type used to specify one or more sample formats. + * The format paInt8. + */ + public static final long SAMPLE_FORMAT_INT8 = 0x00000010; + + /** + * A type used to specify one or more sample formats. + * The format paUInt8. + */ + public static final long SAMPLE_FORMAT_UINT8 = 0x00000020; + + /** + * Flags used to control the behavior of a stream. + * They are passed as parameters to Pa_OpenStream or Pa_OpenDefaultStream. + */ + public static final long STREAM_FLAGS_NO_FLAG = 0; + + /** + * Disable default clipping of out of range samples. + */ + public static final long STREAM_FLAGS_CLIP_OFF = 0x00000001; + + /** + * Disable default dithering. + */ + public static final long STREAM_FLAGS_DITHER_OFF = 0x00000002; + + /** + * Flag requests that where possible a full duplex stream will not discard + * overflowed input samples without calling the stream callback. + * This flag is only valid for full duplex callback streams and only when + * used in combination with the paFramesPerBufferUnspecified (0) + * framesPerBuffer parameter. Using this flag incorrectly results in a + * paInvalidFlag error being returned from + * Pa_OpenStream and Pa_OpenDefaultStream. + */ + public static final long STREAM_FLAGS_NEVER_DROP_INPUT = 0x00000004; + + /** + * Call the stream callback to fill initial output buffers, rather than + * the default behavior of priming the buffers with zeros (silence). + * This flag has no effect for input-only and blocking read/write streams. + */ + public static final long + STREAM_FLAGS_PRIME_OUTPUT_BUFFERS_USING_STREAM_CALLBACK = 0x00000008; + + /** + * A mask specifying the platform specific bits. + */ + public static final long STREAM_FLAGS_PLATFORM_SPECIFIC_FLAGS = 0xFFFF0000; + + /** + * Used when creating new stream parameters for suggested latency. + * To use default value. + */ + public static final double LATENCY_UNSEPCIFIED = 0d; + + /** + * Used when creating new stream parameters for suggested latency. + * To use high input/output value. + */ + public static final double LATENCY_HIGH = -1d; + + /** + * Used when creating new stream parameters for suggested latency. + * To use low input/default value. + */ + public static final double LATENCY_LOW = -2d; + + private static boolean initialized; + + /** + * Used to initialize the portaudio lib. + * + * @throws PortAudioException if error comes from portaudio. + */ + public static synchronized void initialize() + throws PortAudioException + { + if (!initialized) + { + Pa_Initialize(); + initialized = true; + } + } + + /** + * Set params for echocancel and turns on/off noise suppression. + * @param inputStream the input stream. + * @param outputStream the output stream. + * @param enableDenoise is noise suppression enabled. + * @param enableEchoCancel is echo cancel enabled. + * @param frameSize Number of samples to process at one time + * (should correspond to 10-20 ms) + * @param filterLength Number of samples of echo to cancel + * (should generally correspond to 100-500 ms) + */ + public static native void setEchoCancelParams( + long inputStream, + long outputStream, + boolean enableDenoise, + boolean enableEchoCancel, int frameSize, int filterLength); + + /** + * Retrieve the index of the default input device. + * @return The default input device index for the default host API, + * or paNoDevice if no default input device is available or + * an error was encountered. + */ + public static native int Pa_GetDefaultInputDevice(); + + /** + * Retrieve the index of the default output device. + * @return The default input device index for the default host API, + * or paNoDevice if no default input device is available or + * an error was encountered. + */ + public static native int Pa_GetDefaultOutputDevice(); + + /** + * Closes an audio stream. If the audio stream is active it discards + * any pending buffers as if Pa_AbortStream() had been called. + * @param stream the steam pointer. + * @throws PortAudioException + */ + public static native void Pa_CloseStream(long stream) + throws PortAudioException; + + /** + * Terminates audio processing immediately without waiting + * for pending buffers to complete. + * @param stream the steam pointer. + * @throws PortAudioException + */ + public static native void Pa_AbortStream(long stream) + throws PortAudioException; + + /** + * Retrieve the number of available devices. + * The number of available devices may be zero. + * @return the number of devices. + * @throws PortAudioException + */ + public static native int Pa_GetDeviceCount() + throws PortAudioException; + + /** + * Retrieve a pointer to a PaDeviceInfo structure containing + * information about the specified device. + * @param deviceIndex the device index + * @return pointer to device info structure. + */ + public static native long Pa_GetDeviceInfo(int deviceIndex); + + /** + * Library initialization function - call this before using PortAudio.s + * @throws PortAudioException + */ + private static native void Pa_Initialize() + throws PortAudioException; + + /** + * Opens a stream for either input, output or both. + * @param inputParameters the input params or 0 if absent. + * @param outputParameters the ouput params or 0 if absent. + * @param sampleRate The desired sampleRate. + * @param framesPerBuffer The number of frames passed to the stream + * callback function, or the preferred block granularity for + * a blocking read/write stream + * @param streamFlags Flags which modify the + * behaviour of the streaming process. + * @param streamCallback A pointer to a client supplied function that is + * responsible for processing and filling input and output buffers. + * If this parameter is NULL the stream will be opened in + * 'blocking read/write' mode. + * @return pointer to the opened stream. + * @throws PortAudioException + */ + public static native long Pa_OpenStream( + long inputParameters, + long outputParameters, + double sampleRate, + long framesPerBuffer, + long streamFlags, + PortAudioStreamCallback streamCallback) + throws PortAudioException; + + /** + * Commences audio processing. + * @param stream pointer to the stream + * @throws PortAudioException + */ + public static native void Pa_StartStream(long stream) + throws PortAudioException; + + /** + * Terminates audio processing. It waits until all pending audio buffers + * have been played before it returns. + * @param stream pointer to the stream + * @throws PortAudioException + */ + public static native void Pa_StopStream(long stream) + throws PortAudioException; + + /** + * Write samples to an output stream. This function doesn't return until + * the entire buffer has been consumed - this may involve waiting for the + * operating system to consume the data. + * @param stream pointer to the stream + * @param buffer A buffer of sample frames. + * @param frames The number of frames to be written from buffer. + * @throws PortAudioException + */ + public static native void Pa_WriteStream( + long stream, + byte[] buffer, + long frames) + throws PortAudioException; + + /** + * Read samples from an input stream. The function doesn't return until + * the entire buffer has been filled - this may involve waiting for + * the operating system to supply the data. + * @param stream pointer to the stream. + * @param buffer a buffer of sample frames. + * @param frames The number of frames to be read into buffer. + * @throws PortAudioException + */ + public static native void Pa_ReadStream( + long stream, byte[] buffer, long frames) + throws PortAudioException; + + /** + * Retrieve the number of frames that can be read from the stream + * without waiting. + * @param stream pointer to the stream. + * @return returns a non-negative value representing the maximum number + * of frames that can be read from the stream without blocking + * or busy waiting or, a PaErrorCode (which are always negative) + * if PortAudio is not initialized or an error is encountered. + */ + public static native long Pa_GetStreamReadAvailable(long stream); + + /** + * Retrieve the number of frames that can be written to the stream + * without waiting. + * @param stream pointer to the stream. + * @return returns a non-negative value representing the maximum number + * of frames that can be written to the stream without blocking + * or busy waiting or, a PaErrorCode (which are always negative) + * if PortAudio is not initialized or an error is encountered. + */ + public static native long Pa_GetStreamWriteAvailable(long stream); + + /** + * Retrieve the size of a given sample format in bytes. + * @param format the format. + * @return The size in bytes of a single sample in the specified format, + * or paSampleFormatNotSupported if the format is not supported. + */ + public static native int Pa_GetSampleSize(long format); + + /** + * Determine whether it would be possible to open a stream + * with the specified parameters. + * @param inputParameters A structure that describes the + * input parameters used to open a stream. + * @param outputParameters A structure that describes the output + * parameters used to open a stream. + * @param sampleRate The required sampleRate. + * @return returns 0 if the format is supported, and an error code + * indicating why the format is not supported otherwise. + * The constant paFormatIsSupported is provided to compare + * with the return value for success. + */ + public static native boolean Pa_IsFormatSupported( + long inputParameters, + long outputParameters, + double sampleRate); + + /** + * Maximum input channels for the device. + * @param deviceInfo device info pointer. + * @return Maximum input channels for the device. + */ + public static native int PaDeviceInfo_getMaxInputChannels(long deviceInfo); + + /** + * Maximum output channels for the device. + * @param deviceInfo device info pointer. + * @return Maximum output channels for the device. + */ + public static native int PaDeviceInfo_getMaxOutputChannels(long deviceInfo); + + /** + * The name of the device. + * @param deviceInfo device info pointer. + * @return The name of the device. + */ + public static native String PaDeviceInfo_getName(long deviceInfo); + + /** + * The default samplerate for the deviec. + * @param deviceInfo device info pointer. + * @return the default sameple rate for the device. + */ + public static native double PaDeviceInfo_getDefaultSampleRate(long deviceInfo); + + /** + * The host api of the device. + * @param deviceInfo device info pointer. + * @return The host api of the device. + */ + public static native int PaDeviceInfo_getHostApi(long deviceInfo); + + /** + * Returns defaultLowInputLatency for the device. + * @param deviceInfo device info pointer. + * @return defaultLowInputLatency for the device. + */ + public static native double PaDeviceInfo_getDefaultLowInputLatency(long deviceInfo); + + /** + * Returns defaultLowOutputLatency for the device. + * @param deviceInfo device info pointer. + * @return defaultLowOutputLatency for the device. + */ + public static native double PaDeviceInfo_getDefaultLowOutputLatency(long deviceInfo); + + /** + * Returns defaultHighInputLatency for the device. + * @param deviceInfo device info pointer. + * @return defaultHighInputLatency for the device. + */ + public static native double PaDeviceInfo_getDefaultHighInputLatency(long deviceInfo); + + /** + * Returns defaultHighOutputLatency for the device. + * @param deviceInfo device info pointer. + * @return defaultHighOutputLatency for the device. + */ + public static native double PaDeviceInfo_getDefaultHighOutputLatency(long deviceInfo); + + /** + * Retrieve a pointer to a structure containing information + * about a specific host Api. + * @param hostApiIndex host api index. + * @return A pointer to an immutable PaHostApiInfo structure + * describing a specific host API. + */ + public static native long Pa_GetHostApiInfo(int hostApiIndex); + + /** + * The well known unique identifier of this host API. + * @param hostApiInfo pointer to host api info structure. + * @return The well known unique identifier of this host API. + * Enumerator: + paInDevelopment + paDirectSound + paMME + paASIO + paSoundManager + paCoreAudio + paOSS + paALSA + paAL + paBeOS + paWDMKS + paJACK + paWASAPI + paAudioScienceHPI + */ + public static native int PaHostApiInfo_GetType(long hostApiInfo); + + /** + * A textual description of the host API for display on user interfaces. + * @param hostApiInfo pointer to host api info structure. + * @return host api name. + */ + public static native String PaHostApiInfo_GetName(long hostApiInfo); + + /** + * The number of devices belonging to this host API. + * @param hostApiInfo pointer to host api info structure. + * @return The number of devices belonging to this host API. + */ + public static native int PaHostApiInfo_GetDeviceCount(long hostApiInfo); + + /** + * The default input device for this host API. + * @param hostApiInfo pointer to host api info structure. + * @return The default input device for this host API. + */ + public static native int PaHostApiInfo_GetDefaultInputDevice(long hostApiInfo); + + /** + * The default output device for this host API. + * @param hostApiInfo pointer to host api info structure. + * @return The default output device for this host API. + */ + public static native int PaHostApiInfo_GetDefaultOutputDevice(long hostApiInfo); + + /** + * Creates parameters used for opening streams. + * @param deviceIndex the device. + * @param channelCount the channels to be used. + * @param sampleFormat the sample format. + * @param suggestedLatency the suggested latency in milliseconds: + * LATENCY_UNSEPCIFIED - + * use default(default high input/output latency) + * LATENCY_HIGH - use default high input/output latency + * LATENCY_LOW - use default low input/output latency + * ... - any other value in milliseconds (e.g. 0.1 is acceptable) + * @return pointer to the params used for Pa_OpenStream. + */ + public static native long PaStreamParameters_new( + int deviceIndex, + int channelCount, + long sampleFormat, + double suggestedLatency); + + /** + * Prevents the creation of PortAudio instances. + */ + private PortAudio() + { + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudioException.java b/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudioException.java new file mode 100644 index 000000000..0bfe911b8 --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudioException.java @@ -0,0 +1,21 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.portaudio; + +/** + * @author Lubomir Marinov + */ +public class PortAudioException + extends Exception +{ + private static final long serialVersionUID = 0L; + + public PortAudioException(String message) + { + super(message); + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudioManager.java b/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudioManager.java new file mode 100644 index 000000000..e91a96612 --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudioManager.java @@ -0,0 +1,265 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.portaudio; + +import java.util.*; + +import net.java.sip.communicator.impl.neomedia.portaudio.streams.*; + +/** + * Manages PortAudio stream creation and setting necessary properties when using + * them. + * + * @author Damian Minkov + */ +public class PortAudioManager +{ + /** + * 20ms in 8kHz is 160 samples. + */ + public static final int NUM_SAMPLES = 160; + + /** + * The static instance of portaudio manager. + */ + private static PortAudioManager instance = null; + + private Hashtable inputStreams = + new Hashtable(); + + private ArrayList outputStreams = + new ArrayList(); + + /** + * default values for the params. + */ + private boolean enabledEchoCancel = false; + private boolean enabledDeNoise = true; + private int frameSize = NUM_SAMPLES; + private int filterLength = 2048; + + private static double suggestedLatency = PortAudio.LATENCY_UNSEPCIFIED; + + /** + * Private constructor as we have one static instance of this manager. + * @throws PortAudioException + */ + private PortAudioManager() + throws PortAudioException + { + PortAudio.initialize(); + } + + /** + * Gets the only instance of PortAudioManager, if its not already created + * will be created. + * @return the static instance. + * @throws PortAudioException if portaudio cannot be initialized for + * some reason. + */ + public static PortAudioManager getInstance() + throws PortAudioException + { + if(instance == null) + instance = new PortAudioManager(); + return instance; + } + + /** + * Creates input stream from the device with given index. + * @param deviceIndex the device index. + * @param sampleRate the sample rate to use, its the sample rate of the + * input stream. + * @param channels the channels that the stream will serve. + * @return the stream. + * @throws PortAudioException if opening of the stream failes. + */ + public InputPortAudioStream getInputStream( + int deviceIndex, double sampleRate, int channels) + throws PortAudioException + { + MasterPortAudioStream st = inputStreams.get(deviceIndex); + if(st == null) + { + st = new MasterPortAudioStream(deviceIndex, sampleRate, channels); + inputStreams.put(deviceIndex, st); + + // if there is a output streams, get the latest one + // and connect them + // todo: we must link input to all outputs ??? + if(isEnabledEchoCancel() && outputStreams.size() > 0) + { + OutputPortAudioStream out = outputStreams.get( + outputStreams.size() - 1); + st.setParams(out, isEnabledDeNoise(), + isEnabledEchoCancel(), getFrameSize(), getFilterLength()); + } + else + st.setParams(null, isEnabledDeNoise(), + isEnabledEchoCancel(), getFrameSize(), getFilterLength()); + } + + return new InputPortAudioStream(st); + } + + /** + * Creates output stream from the device with given index. + * @param deviceIndex the device index. + * @param sampleRate the sample rate to use, its the sample rate of the + * output stream. + * @param channels the channels that the stream will serve. + * @return the stream. + * @throws PortAudioException if opening of the stream failes. + */ + public OutputPortAudioStream getOutputStream( + int deviceIndex, double sampleRate, int channels) + throws PortAudioException + { + OutputPortAudioStream out = + new OutputPortAudioStream(deviceIndex, sampleRate, channels); + outputStreams.add(out); + + // if there are input streams created, get the first one + // and link it to this output + // todo: what to do with the others + if(isEnabledEchoCancel() && inputStreams.size() > 0) + { + MasterPortAudioStream st = inputStreams.values().iterator().next(); + + st.setParams(out, isEnabledEchoCancel(), + isEnabledDeNoise(), getFrameSize(), getFilterLength()); + } + + return out; + } + + /** + * Output stream is stopped. + * @param st the stream that is stopped. + */ + public void stoppedOutputPortAudioStream(OutputPortAudioStream st) + { + outputStreams.remove(st); + } + + /** + * Input stream is stopped. + * @param st the input stream that is stopped. + */ + public void stoppedInputPortAudioStream(MasterPortAudioStream st) + { + inputStreams.remove(st.getDeviceIndex()); + } + + /** + * Creates output stream from the device with given index. + * @param deviceIndex the device index. + * @param sampleRate the sample rate to use, its the sample rate of the + * output stream. + * @param channels the channels that the stream will serve. + * @param sampleFormat the format the will be used by the stream. + * @return the stream. + * @throws PortAudioException if opening of the stream failes. + */ + public OutputPortAudioStream getOutputStream( + int deviceIndex, double sampleRate, int channels, long sampleFormat) + throws PortAudioException + { + return new OutputPortAudioStream( + deviceIndex, sampleRate, channels, sampleFormat); + } + + /** + * Enables or disables echo cancel. + * @param enabled should we enable or disable echo cancelation + * @param frameSize Number of samples to process at one time + * (should correspond to 10-20 ms) + * @param filterLength Number of samples of echo to cancel + * (should generally correspond to 100-500 ms) + */ + public void setEchoCancel(boolean enabled, int frameSize, int filterLength) + { + this.enabledEchoCancel = enabled; + this.frameSize = frameSize; + this.filterLength = filterLength; + } + + /** + * Enables or disables noise suppression. + * @param enabled should we enable or disable noise suppression. + */ + public void setDeNoise(boolean enabled) + { + this.enabledDeNoise = enabled; + } + + /** + * Returns the default values of the latency to be used when + * openning new streams. + * @return the latency. + */ + public static double getSuggestedLatency() + { + if(suggestedLatency != PortAudio.LATENCY_UNSEPCIFIED) + return suggestedLatency; + + String osName = System.getProperty("os.name"); + if (osName.startsWith("Mac")) + return PortAudio.LATENCY_HIGH; + else if (osName.startsWith("Linux")) + return PortAudio.LATENCY_HIGH; + else if (osName.startsWith("Windows")) + return 0.1d; + return PortAudio.LATENCY_UNSEPCIFIED; + } + + /** + * Changes the suggested latency. + * @param aSuggestedLatency the suggestedLatency to set. + */ + public static void setSuggestedLatency(double aSuggestedLatency) + { + suggestedLatency = aSuggestedLatency; + } + + /** + * Is echo cancel enabled. + * @return true if echo cancel is enabled, false otherwise. + */ + public boolean isEnabledEchoCancel() + { + return enabledEchoCancel; + } + + /** + * Is noise reduction enabled. + * @return true if noise reduction is enabled, false otherwise. + */ + public boolean isEnabledDeNoise() + { + return enabledDeNoise; + } + + /** + * Number of samples to process at one time (should correspond to 10-20 ms). + * @return the frameSize. + */ + public int getFrameSize() + { + return frameSize; + } + + /** + * Number of samples of echo to cancel + * (should generally correspond to 100-500 ms) + * @return the filterLength. + */ + public int getFilterLength() + { + return filterLength; + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudioStreamCallback.java b/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudioStreamCallback.java new file mode 100644 index 000000000..c91f2119a --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudioStreamCallback.java @@ -0,0 +1,25 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.portaudio; + +import java.nio.*; + +/** + * @author Lubomir Marinov + */ +public interface PortAudioStreamCallback +{ + public static final int RESULT_ABORT = 2; + + public static final int RESULT_COMPLETE = 1; + + public static final int RESULT_CONTINUE = 0; + + public int callback(ByteBuffer input, ByteBuffer output); + + public void finishedCallback(); +} diff --git a/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudioUtils.java b/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudioUtils.java new file mode 100644 index 000000000..2f9ba3766 --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudioUtils.java @@ -0,0 +1,49 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.portaudio; + +import javax.media.*; + +/** + * Common used util methods concerning PortAudio. + * @author Damian Minkov + */ +public class PortAudioUtils +{ + /** + * The locator prefix used when creating or parsing MediaLocators. + */ + public static final String LOCATOR_PREFIX = "portaudio:#"; + + /** + * Extracts the device index from the locator. + * @param locator the locator containing the device index. + * @return the extracted device index. + */ + public static int getDeviceIndexFromLocator(MediaLocator locator) + { + return Integer.parseInt(locator.toExternalForm().replace( + LOCATOR_PREFIX, "")); + } + + /** + * Returns the PortAudio sample format. + * @param sampleSizeInBits the size in bits. + * @return the portaudio sampleformat. + */ + public static long getPortAudioSampleFormat(int sampleSizeInBits) + { + switch(sampleSizeInBits) + { + case 8 : return PortAudio.SAMPLE_FORMAT_INT8; + case 16 : return PortAudio.SAMPLE_FORMAT_INT16; + case 24 : return PortAudio.SAMPLE_FORMAT_INT24; + case 32 : return PortAudio.SAMPLE_FORMAT_INT32; + default : return PortAudio.SAMPLE_FORMAT_INT16; + } + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/InputPortAudioStream.java b/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/InputPortAudioStream.java new file mode 100644 index 000000000..3b2e56ad8 --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/InputPortAudioStream.java @@ -0,0 +1,96 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.portaudio.streams; + +import net.java.sip.communicator.impl.neomedia.portaudio.PortAudioException; +import net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio.*; + +/** + * The input audio stream. + * + * @author Damian Minkov + */ +public class InputPortAudioStream +{ + private final MasterPortAudioStream parentStream; + + private boolean started = false; + + /** + * The buffer to return. + */ + protected byte[] buffer = null; + + /** + * Creates new input stream (slave) with master input stream. + * @param st the parent(master) input stream. + */ + public InputPortAudioStream(MasterPortAudioStream st) + { + this.parentStream = st; + } + + /** + * Block and read a buffer from the stream if there is no buffer. + * + * @return the bytes that a read from underlying stream. + * @throws PortAudioException if an error occurs while reading. + */ + public byte[] read() + throws PortAudioException + { + synchronized(parentStream) + { + byte[] res = buffer; + + if(res == null) + res = parentStream.read(); + buffer = null; + return res; + } + } + + /** + * Starts the stream. Also starts the parent stream + * if its not already started. + * @throws PortAudioException if stream cannot be started. + */ + public synchronized void start() + throws PortAudioException + { + if(started) + return; + + parentStream.start(this); + started = true; + } + + /** + * Stops the stream. Also stops the parent if we are the last slave + * stream that use it. + * @throws PortAudioException + */ + public synchronized void stop() + throws PortAudioException + { + if(!started) + return; + + parentStream.stop(this); + started = false; + } + + /** + * The parent can set a buffer that was requested and read by other + * slave stream. + * @param buffer the buffer to set. + */ + public void setBuffer(byte[] buffer) + { + this.buffer = buffer; + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/MasterPortAudioStream.java b/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/MasterPortAudioStream.java new file mode 100644 index 000000000..4a12dbbae --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/MasterPortAudioStream.java @@ -0,0 +1,197 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.portaudio.streams; + +import net.java.sip.communicator.impl.neomedia.portaudio.PortAudioManager; +import net.java.sip.communicator.impl.neomedia.portaudio.PortAudio; +import net.java.sip.communicator.impl.neomedia.portaudio.PortAudioException; +import java.util.*; +import net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio.*; + +/** + * The master audio stream which opens the PortAudio stream and reads from it. + * We can have multiple slave input streams that are connected to this master + * stream. + * + * @author Damian Minkov + * @author Lubomir Marinov + */ +public class MasterPortAudioStream +{ + private int deviceIndex = -1; + + private long stream = 0; + + private boolean started = false; + + private int frameSize; + + private int numberOfStarts = 0; + + double sampleRate; + int channels; + + private final List slaves + = new ArrayList(); + + /** + * Creates new stream. + * @param deviceIndex the device to use. + * @param channels the channels to serve. + * @param sampleRate the sample rate. + * @throws PortAudioException if stream cannot be opened. + */ + public MasterPortAudioStream( + int deviceIndex, double sampleRate, int channels) + throws PortAudioException + { + this.deviceIndex = deviceIndex; + this.sampleRate = sampleRate; + this.channels = channels; + + initStream(); + + frameSize + = PortAudio.Pa_GetSampleSize(PortAudio.SAMPLE_FORMAT_INT16) + * channels; + } + + /** + * Create the stream. + * @throws PortAudioException if stream cannot be opened. + */ + private void initStream() + throws PortAudioException + { + long parameters = PortAudio.PaStreamParameters_new( + deviceIndex, + channels, + PortAudio.SAMPLE_FORMAT_INT16, + PortAudioManager.getSuggestedLatency()); + + stream = PortAudio.Pa_OpenStream( + parameters, + 0, // no output parameters + sampleRate, + PortAudio.FRAMES_PER_BUFFER_UNSPECIFIED, + PortAudio.STREAM_FLAGS_CLIP_OFF + | PortAudio.STREAM_FLAGS_DITHER_OFF, + null); + } + + /** + * Starts the stream operation if not already started + * and stores the slave inputstream + * that starts us. + * @throws PortAudioException + */ + synchronized void start(InputPortAudioStream slave) + throws PortAudioException + { + if(numberOfStarts == 0) + { + if(stream == 0) + initStream(); + + // start + PortAudio.Pa_StartStream(stream); + started = true; + } + + slaves.add(slave); + numberOfStarts++; + } + + /** + * Stops the PortAudio stream if requested by the last stream that uses us. + * @throws PortAudioException + */ + synchronized void stop(InputPortAudioStream slave) + throws PortAudioException + { + if(!started) + return; + + slaves.remove(slave); + numberOfStarts--; + + if(numberOfStarts == 0) + { + // stop + PortAudio.Pa_CloseStream(stream); + stream = 0; + started = false; + PortAudioManager.getInstance().stoppedInputPortAudioStream(this); + } + } + + /** + * Returns the index of the device that we use. + * @return the deviceIndex + */ + public int getDeviceIndex() + { + return deviceIndex; + } + + /** + * Returns the pointer to the stream that we use for reading. + * @return the stream pointer. + */ + public long getStream() + { + return stream; + } + + /** + * Block and read a buffer from the stream. + * + * @return the bytes that a read from underlying stream. + * @throws PortAudioException if an error occurs while reading. + */ + public byte[] read() + throws PortAudioException + { + if(!started) + return new byte[0]; + + byte[] bytebuff = new byte[PortAudioManager.NUM_SAMPLES*frameSize]; + PortAudio.Pa_ReadStream( + stream, bytebuff, PortAudioManager.NUM_SAMPLES); + + for(InputPortAudioStream slave : slaves) + slave.setBuffer(bytebuff); + + return bytebuff; + } + + /** + * Sets parameters to the underlying stream. + * @param out the connected output stream if echo cancel is enabled. + * @param deNoiseEnabled true if we want to enable noise reduction. + * @param echoCancelEnabled true to enable echo cancel. + * @param frameSize Number of samples to process at one time + * (should correspond to 10-20 ms). + * @param filterLength Number of samples of echo to cancel + * (should generally correspond to 100-500 ms) + */ + public void setParams(OutputPortAudioStream out, + boolean deNoiseEnabled, + boolean echoCancelEnabled, int frameSize, int filterLength) + { + long outStream = 0; + + if(out != null) + outStream = out.getStream(); + + PortAudio.setEchoCancelParams( + stream, + outStream, + deNoiseEnabled, + echoCancelEnabled, frameSize, filterLength); + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/OutputPortAudioStream.java b/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/OutputPortAudioStream.java new file mode 100644 index 000000000..50879dd31 --- /dev/null +++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/OutputPortAudioStream.java @@ -0,0 +1,222 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.neomedia.portaudio.streams; + +import net.java.sip.communicator.impl.neomedia.portaudio.PortAudioManager; +import net.java.sip.communicator.impl.neomedia.portaudio.PortAudio; +import net.java.sip.communicator.impl.neomedia.portaudio.PortAudioException; +import net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio.*; + +/** + * The output stream that opens and writes to the PortAudio stream. + * + * @author Damian Minkov + */ +public class OutputPortAudioStream +{ + private int deviceIndex = -1; + private long stream = 0; + private byte[] bufferLeft = null; + private int frameSize; + private boolean started = false; + + private double sampleRate; + private int channels; + private long sampleFormat; + + /** + * Creates output stream. + * @param deviceIndex the index of the device to use. + * @param sampleRate the samepl rate. + * @param channels the channels to serve. + * @throws PortAudioException if stream fails to open. + */ + public OutputPortAudioStream( + int deviceIndex, double sampleRate, int channels) + throws PortAudioException + { + this(deviceIndex, sampleRate, channels, PortAudio.SAMPLE_FORMAT_INT16); + } + + /** + * Creates output stream. + * @param deviceIndex the index of the device to use. + * @param sampleRate the samepl rate. + * @param channels the channels to serve. + * @param sampleFormat the sample format to use. + * @throws PortAudioException if stream fails to open. + */ + public OutputPortAudioStream( + int deviceIndex, double sampleRate, int channels, long sampleFormat) + throws PortAudioException + { + this.deviceIndex = deviceIndex; + this.sampleRate = sampleRate; + this.channels = channels; + this.sampleFormat = sampleFormat; + + initStream(); + + frameSize = PortAudio.Pa_GetSampleSize(sampleFormat)*channels; + } + + /** + * Creates the PortAudio stream. + * @throws PortAudioException if stream fails to open. + */ + private void initStream() + throws PortAudioException + { + long parameters = PortAudio.PaStreamParameters_new( + getDeviceIndex(),channels, + sampleFormat, + PortAudioManager.getSuggestedLatency()); + + stream = PortAudio.Pa_OpenStream( + 0, + parameters, + sampleRate, + PortAudio.FRAMES_PER_BUFFER_UNSPECIFIED, + PortAudio.STREAM_FLAGS_CLIP_OFF + | PortAudio.STREAM_FLAGS_DITHER_OFF, + null); + } + + /** + * We will split everything into parts of PortAudioManager.NUM_SAMPLES. + * If something is left we will save it for next write and use it than. + * + * @param buffer the current buffer. + * @throws PortAudioException error while writing to device. + */ + public synchronized void write(byte[] buffer) + throws PortAudioException + { + if(!started) + return; + + int numSamples = PortAudioManager.NUM_SAMPLES*frameSize; + + int currentIx = 0; + + // if there are bytes from previous run + if(bufferLeft != null && bufferLeft.length > 0) + { + if(buffer.length + bufferLeft.length >= numSamples) + { + byte[] tmp = new byte[numSamples]; + System.arraycopy(bufferLeft, 0, tmp, 0, bufferLeft.length); + System.arraycopy(buffer, currentIx, tmp, + bufferLeft.length, numSamples - bufferLeft.length); + currentIx += numSamples - bufferLeft.length; + bufferLeft = null; + + PortAudio.Pa_WriteStream( + getStream(),tmp, tmp.length/frameSize); + } + else + { + // not enough bytes even with previous left + // so let store everything + byte[] tmp = new byte[numSamples]; + System.arraycopy(bufferLeft, 0, tmp, 0, bufferLeft.length); + System.arraycopy(buffer, currentIx, tmp, + bufferLeft.length, numSamples - bufferLeft.length); + bufferLeft = null; + return; + } + } + + // now use all the current buffer + if(buffer.length > numSamples) + { + while(currentIx <= buffer.length - numSamples) + { + byte[] tmp = new byte[numSamples]; + System.arraycopy(buffer, currentIx, tmp, 0, numSamples); + + PortAudio.Pa_WriteStream( + getStream(),tmp, tmp.length/frameSize); + currentIx += numSamples; + } + + if(currentIx < buffer.length) + { + bufferLeft = new byte[buffer.length - currentIx]; + System.arraycopy(buffer, currentIx, bufferLeft, 0, bufferLeft.length); + } + } + else if(buffer.length < numSamples) + { + bufferLeft = buffer; + } + else + { + PortAudio.Pa_WriteStream( + getStream(),buffer, buffer.length/frameSize); + } + + } + + /** + * Starts the stream operation + * @throws PortAudioException + */ + public synchronized void start() + throws PortAudioException + { + if(started) + return; + + if(getStream() == 0) + initStream(); + + // start + PortAudio.Pa_StartStream(getStream()); + started = true; + } + + /** + * Stops the stream operation. + * @throws PortAudioException + */ + public void stop() + throws PortAudioException + { + if(!started) + return; + + // stop + PortAudio.Pa_CloseStream(getStream()); + + synchronized(this) + { + stream = 0; + bufferLeft = null; + started = false; + PortAudioManager.getInstance().stoppedOutputPortAudioStream(this); + } + } + + /** + * The index of the device that we use. + * @return the deviceIndex + */ + public int getDeviceIndex() + { + return deviceIndex; + } + + /** + * The pointer of the PortAudio stream. + * @return the stream pointer. + */ + public long getStream() + { + return stream; + } +}