diff --git a/lib/native/linux-64/libjportaudio.so b/lib/native/linux-64/libjportaudio.so index 8f01f0789..f71721763 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 3fd7e3d8b..914c741bc 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 fb249d3f2..db2fa9c3c 100755 Binary files a/lib/native/mac/libjportaudio.jnilib and b/lib/native/mac/libjportaudio.jnilib differ diff --git a/src/native/portaudio/Makefile b/src/native/portaudio/Makefile index 00749bd76..160f97b1c 100644 --- a/src/native/portaudio/Makefile +++ b/src/native/portaudio/Makefile @@ -9,8 +9,8 @@ CPPFLAGS=-DJNI_IMPLEMENTATION \ -Wall -Wreturn-type \ -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux \ -I$(PORTAUDIO_HOME)/include -LDFLAGS=-shared -fPIC -LIBS=-L$(PORTAUDIO_HOME)/lib/.libs -static -lportaudio +LDFLAGS=-shared +LIBS=-L$(PORTAUDIO_HOME)/lib/.libs -lasound -lm -lpthread -ljack -static -lportaudio $(TARGET): net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio.c net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio.h $(CC) $(CPPFLAGS) $< $(LDFLAGS) -o $@ $(LIBS) diff --git a/src/native/portaudio/net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio.c b/src/native/portaudio/net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio.c index dd28acfcb..ffa388da0 100644 --- a/src/native/portaudio/net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio.c +++ b/src/native/portaudio/net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio.c @@ -292,6 +292,34 @@ Java_net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio_PaDeviceI return ((PaDeviceInfo *) deviceInfo)->hostApi; } +JNIEXPORT jdouble JNICALL +Java_net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowInputLatency + (JNIEnv *env, jclass clazz, jlong deviceInfo) +{ + return ((PaDeviceInfo *) deviceInfo)->defaultLowInputLatency; +} + +JNIEXPORT jdouble JNICALL +Java_net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowOutputLatency + (JNIEnv *env, jclass clazz, jlong deviceInfo) +{ + return ((PaDeviceInfo *) deviceInfo)->defaultLowOutputLatency; +} + +JNIEXPORT jdouble JNICALL +Java_net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighInputLatency + (JNIEnv *env, jclass clazz, jlong deviceInfo) +{ + return ((PaDeviceInfo *) deviceInfo)->defaultHighInputLatency; +} + +JNIEXPORT jdouble JNICALL +Java_net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighOutputLatency + (JNIEnv *env, jclass clazz, jlong deviceInfo) +{ + return ((PaDeviceInfo *) deviceInfo)->defaultHighOutputLatency; +} + JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio_Pa_1GetHostApiInfo (JNIEnv *env , jclass clazz, jint hostApiIndex) @@ -352,7 +380,7 @@ Java_net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio_PaStreamP streamParameters->device = deviceIndex; streamParameters->channelCount = channelCount; streamParameters->sampleFormat = sampleFormat; - streamParameters->suggestedLatency = 0,4; + streamParameters->suggestedLatency = 0; streamParameters->hostApiSpecificStreamInfo = NULL; } return (jlong) streamParameters; @@ -367,8 +395,13 @@ PortAudio_fixInputParametersSuggestedLatency( PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(inputParameters->device); if (deviceInfo) - inputParameters->suggestedLatency - = deviceInfo->defaultHighInputLatency; + { + // default latency of 100ms seems ok + // to use portaudio on all systems + inputParameters->suggestedLatency + = 0.1; //= deviceInfo->defaultLowInputLatency; + + } } return inputParameters; } @@ -383,7 +416,7 @@ PortAudio_fixOutputParametersSuggestedLatency( if (deviceInfo) outputParameters->suggestedLatency - = deviceInfo->defaultHighOutputLatency; + = deviceInfo->defaultLowOutputLatency; } return outputParameters; } diff --git a/src/native/portaudio/net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio.h b/src/native/portaudio/net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio.h index d0535778a..56906fc6e 100644 --- a/src/native/portaudio/net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio.h +++ b/src/native/portaudio/net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio.h @@ -167,6 +167,38 @@ JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_media_protocol_por JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio_PaDeviceInfo_1getHostApi (JNIEnv *, jclass, jlong); +/* + * Class: net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio + * Method: PaDeviceInfo_getDefaultLowInputLatency + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowInputLatency + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio + * Method: PaDeviceInfo_getDefaultLowOutputLatency + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowOutputLatency + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio + * Method: PaDeviceInfo_getDefaultHighInputLatency + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighInputLatency + (JNIEnv *, jclass, jlong); + +/* + * Class: net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio + * Method: PaDeviceInfo_getDefaultHighOutputLatency + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighOutputLatency + (JNIEnv *, jclass, jlong); + /* * Class: net_java_sip_communicator_impl_media_protocol_portaudio_PortAudio * Method: Pa_GetHostApiInfo diff --git a/src/net/java/sip/communicator/impl/media/protocol/portaudio/PortAudio.java b/src/net/java/sip/communicator/impl/media/protocol/portaudio/PortAudio.java index d1f207fce..ce5a0f29a 100644 --- a/src/net/java/sip/communicator/impl/media/protocol/portaudio/PortAudio.java +++ b/src/net/java/sip/communicator/impl/media/protocol/portaudio/PortAudio.java @@ -36,6 +36,40 @@ public final class PortAudio */ 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; + private static boolean initialized; /** @@ -256,6 +290,34 @@ public static native boolean Pa_IsFormatSupported( */ 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. diff --git a/src/net/java/sip/communicator/impl/media/renderer/audio/PortAudioRenderer.java b/src/net/java/sip/communicator/impl/media/renderer/audio/PortAudioRenderer.java index 64b4e845b..12ae0e8e4 100644 --- a/src/net/java/sip/communicator/impl/media/renderer/audio/PortAudioRenderer.java +++ b/src/net/java/sip/communicator/impl/media/renderer/audio/PortAudioRenderer.java @@ -160,20 +160,9 @@ public void open() { if (stream == 0) { - long streamParameters - = PortAudio.PaStreamParameters_new( - deviceIndex, - audioFormat.getChannels(), - PortAudio.SAMPLE_FORMAT_INT16); - - stream - = PortAudio.Pa_OpenStream( - 0, - streamParameters, - audioFormat.getSampleRate(), - PortAudio.FRAMES_PER_BUFFER_UNSPECIFIED, - PortAudio.STREAM_FLAGS_NO_FLAG, - null); + // lets try three times to open the device + // and wait 250 ms. between retries. + stream = openStreamRetring(3, 250); } } catch (PortAudioException e) @@ -182,6 +171,50 @@ public void open() } } + /** + * When opening the device notifications maybe running so we will retry + * opening the device. + * @param numOfRetries the number of tries to open the requested device. + * @param interval the interval to wait between retries in miliseconds. + * @return the stream pointer. + * @throws PortAudioException the exception to be thrown if device + * fail to open and after the last try. + */ + private long openStreamRetring(int numOfRetries, int interval) + throws PortAudioException + { + for(int i = 0; i < numOfRetries; i++) + { + try + { + long streamParameters + = PortAudio.PaStreamParameters_new( + deviceIndex, + audioFormat.getChannels(), + PortAudio.SAMPLE_FORMAT_INT16); + + return PortAudio.Pa_OpenStream( + 0, + streamParameters, + audioFormat.getSampleRate(), + PortAudio.FRAMES_PER_BUFFER_UNSPECIFIED, + PortAudio.STREAM_FLAGS_CLIP_OFF + | PortAudio.STREAM_FLAGS_DITHER_OFF, + null); + } + catch (PortAudioException e) + { + if(i == numOfRetries - 1) + throw e; + else + try + {Thread.sleep(interval);}catch(InterruptedException ex){} + } + } + + return 0; + } + /** * Closes the plug-in. */