From de4f2d14bb629cfbdfc5d46ef684d6a6e3350eb0 Mon Sep 17 00:00:00 2001 From: Damian Minkov Date: Wed, 20 Jan 2010 10:49:41 +0000 Subject: [PATCH] Move portaudio specific settings from DeviceConfiguration to PortAudioAuto, and leave stopping only to portaudio slave streams. --- .../neomedia/device/DeviceConfiguration.java | 67 ++---------------- .../impl/neomedia/device/PortAudioAuto.java | 70 ++++++++++++++++++- .../impl/neomedia/portaudio/PortAudio.java | 9 +-- .../streams/InputPortAudioStream.java | 20 +++++- .../streams/MasterPortAudioStream.java | 47 +++---------- 5 files changed, 106 insertions(+), 107 deletions(-) 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 33723d9ec..2abaa1f52 100644 --- a/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java +++ b/src/net/java/sip/communicator/impl/neomedia/device/DeviceConfiguration.java @@ -112,26 +112,26 @@ public class DeviceConfiguration /** * Property used to store is echo cancel enabled or disabled. */ - private static final String PROP_AUDIO_ECHOCANCEL_ENABLED = + static final String PROP_AUDIO_ECHOCANCEL_ENABLED = "net.java.sip.communicator.impl.neomedia.echocancel"; /** * Property used to store the echo cancel tail used for cancelation. */ - private static final String PROP_AUDIO_ECHOCANCEL_TAIL = + static final String PROP_AUDIO_ECHOCANCEL_TAIL = "net.java.sip.communicator.impl.neomedia.echocancel.tail"; /** * Property used to store is denoise enabled or disabled. */ - private static final String PROP_AUDIO_DENOISE_ENABLED = + static final String PROP_AUDIO_DENOISE_ENABLED = "net.java.sip.communicator.impl.neomedia.denoise"; /** * Property used to store the latency option we use for current OS. * Must be in milliseconds. */ - private static final String PROP_AUDIO_LATENCY = + static final String PROP_AUDIO_LATENCY = "net.java.sip.communicator.impl.neomedia.latency"; /** @@ -222,28 +222,12 @@ else if (audioCaptureDevices.length < 1) + " capture devices: " + audioCaptureDevices); String audioDevName = config.getString(PROP_AUDIO_DEVICE); - boolean errorStartingPA = false; - - try - { - // as here is the first entry when starting up - // we will create the instance of portaudio manager - // and if there are exceptions like missing binary - // will be back to javasound - - // this will create portaudio instance - PortAudioManager.getInstance().isEnabledEchoCancel(); - } - catch (Throwable e) - { - errorStartingPA = true; - } if(audioDevName == null) { // the default behaviour if nothing set is to use javasound // this will also choose the capture device - if(!errorStartingPA) + if(PortAudioAuto.isSupported()) { setAudioSystem(AUDIO_SYSTEM_PORTAUDIO, null, false); } @@ -267,7 +251,7 @@ else if (audioCaptureDevices.length < 1) } } - if(getAudioSystem() == null || errorStartingPA) + if(getAudioSystem() == null || !PortAudioAuto.isSupported()) { logger.warn("Computer sound config changed or " + "there is a problem since last config was saved, " + @@ -281,45 +265,6 @@ else if (audioCaptureDevices.length < 1) if (audioCaptureDevice != null) logger.info("Found " + audioCaptureDevice.getName() + " as an audio capture device."); - - // now extract other sound related configs - if(!errorStartingPA) - { - try - { - boolean echoCancelEnabled = - config.getBoolean(PROP_AUDIO_ECHOCANCEL_ENABLED, - PortAudioManager.getInstance().isEnabledEchoCancel()); - if(echoCancelEnabled) - { - int echoCancelTail = - config.getInt(PROP_AUDIO_ECHOCANCEL_TAIL, - PortAudioManager.getInstance().getFilterLength()); - PortAudioManager.getInstance().setEchoCancel( - echoCancelEnabled, - PortAudioManager.getInstance().getFrameSize(), - echoCancelTail); - } - - boolean denoiseEnabled = - config.getBoolean(PROP_AUDIO_DENOISE_ENABLED, - PortAudioManager.getInstance().isEnabledDeNoise()); - PortAudioManager.getInstance().setDeNoise(denoiseEnabled); - - // suggested latency is saved in configuration as - // milliseconds but PortAudioManager use it as seconds - int audioLatency = config.getInt(PROP_AUDIO_LATENCY, - (int)(PortAudioManager.getSuggestedLatency()*1000)); - if(audioLatency != - (int)PortAudioManager.getSuggestedLatency()*1000) - PortAudioManager.setSuggestedLatency( - (double)audioLatency/1000d); - } - catch (Exception e) - { - logger.error("Error parsing audio config", e); - } - } } if (config.getBoolean(PROP_VIDEO_DEVICE_IS_DISABLED, false)) 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 8ad571c80..aaea7be92 100644 --- a/src/net/java/sip/communicator/impl/neomedia/device/PortAudioAuto.java +++ b/src/net/java/sip/communicator/impl/neomedia/device/PortAudioAuto.java @@ -10,9 +10,11 @@ import javax.media.*; +import net.java.sip.communicator.impl.neomedia.*; 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 net.java.sip.communicator.service.configuration.*; import com.sun.media.util.*; @@ -24,6 +26,12 @@ */ public class PortAudioAuto { + /** + * The Logger used by the PortAudioAuto class and its + * instances for logging output. + */ + private static final Logger logger = Logger.getLogger(PortAudioAuto.class); + /** * An array of the devices that can be used for playback. */ @@ -39,6 +47,11 @@ public class PortAudioAuto */ public static CaptureDeviceInfo defaultCaptureDevice = null; + /** + * Is portaudio supported on current platform. + */ + private static boolean supported = false; + /** * Initializes a new PortAudioAuto instance which creates PortAudio * capture devices by enumerating all host devices with input channels. @@ -55,7 +68,7 @@ public class PortAudioAuto PortAudioManager.getInstance(); // enable jmf logging, so we can track codec chains and formats - if(Logger.getLogger(PortAudioAuto.class).isDebugEnabled()) + if(logger.isDebugEnabled()) Registry.set("allowLogging", true); int deviceCount = PortAudio.Pa_GetDeviceCount(); @@ -105,5 +118,60 @@ public class PortAudioAuto // now add it as available audio system to DeviceConfiguration DeviceConfiguration.addAudioSystem( DeviceConfiguration.AUDIO_SYSTEM_PORTAUDIO); + + // now extract other sound related configs + try + { + ConfigurationService config + = NeomediaActivator.getConfigurationService(); + + boolean echoCancelEnabled = + config.getBoolean( + DeviceConfiguration.PROP_AUDIO_ECHOCANCEL_ENABLED, + PortAudioManager.getInstance().isEnabledEchoCancel()); + if(echoCancelEnabled) + { + int echoCancelTail = + config.getInt( + DeviceConfiguration.PROP_AUDIO_ECHOCANCEL_TAIL, + PortAudioManager.getInstance().getFilterLength()); + PortAudioManager.getInstance().setEchoCancel( + echoCancelEnabled, + PortAudioManager.getInstance().getFrameSize(), + echoCancelTail); + } + + boolean denoiseEnabled = + config.getBoolean( + DeviceConfiguration.PROP_AUDIO_DENOISE_ENABLED, + PortAudioManager.getInstance().isEnabledDeNoise()); + PortAudioManager.getInstance().setDeNoise(denoiseEnabled); + + // suggested latency is saved in configuration as + // milliseconds but PortAudioManager use it as seconds + int audioLatency = config.getInt( + DeviceConfiguration.PROP_AUDIO_LATENCY, + (int)(PortAudioManager.getSuggestedLatency()*1000)); + if(audioLatency != + (int)PortAudioManager.getSuggestedLatency()*1000) + PortAudioManager.setSuggestedLatency( + (double)audioLatency/1000d); + } + catch (Exception e) + { + logger.error("Error parsing audio config", e); + } + + + supported = true; + } + + /** + * Whether portaudio is supported. + * @return the supported + */ + public static boolean isSupported() + { + return supported; } } diff --git a/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudio.java b/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudio.java index ec29546c3..ae5ca7229 100644 --- a/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudio.java +++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/PortAudio.java @@ -14,14 +14,7 @@ public final class PortAudio { static { - try - { - System.loadLibrary("jportaudio"); - } - catch (Throwable e) - { - System.out.println("Missing portaudio binary"); - } + System.loadLibrary("jportaudio"); } /** 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 index e1a3ff7d9..dc6b42e49 100644 --- a/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/InputPortAudioStream.java +++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/InputPortAudioStream.java @@ -15,10 +15,24 @@ */ public class InputPortAudioStream { + /** + * Our parent stream, the actual source of data. + */ private final MasterPortAudioStream parentStream; + /** + * Is this stream started. + */ private boolean started = false; + /** + * This is unprotected field which will stop any further reading, + * as read is synchronized sometimes there maybe some delay + * before we are stopped, as reading is too aggressive stopping thread may + * even wait more than 20 seconds. + */ + private boolean stopping = false; + /** * The buffer to return. */ @@ -42,6 +56,9 @@ public InputPortAudioStream(MasterPortAudioStream st) public byte[] read() throws PortAudioException { + if(stopping || !started) + return new byte[0]; + synchronized(parentStream) { byte[] res = buffer; @@ -78,9 +95,10 @@ public synchronized void stop() { if(started) { - parentStream.setStopping(true); + stopping = true; parentStream.stop(this); started = false; + stopping = false; } } 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 index 7b1611135..291931ec9 100644 --- a/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/MasterPortAudioStream.java +++ b/src/net/java/sip/communicator/impl/neomedia/portaudio/streams/MasterPortAudioStream.java @@ -58,15 +58,6 @@ public class MasterPortAudioStream */ private Object connectedToStreamSync = new Object(); - /** - * Other using MasterPortAudioStream may inform us that will stop us. - * This is unprotected field which will stop any further reading, - * as read is synchronized sometimes there maybe some delay - * before we are stopped, as reading is too aggressive stopping thread may - * even wait more than 20 seconds. - */ - private boolean stopping = false; - /** * The InputPortAudioStreams which read audio from this * MasterPortAudioStreams. @@ -178,7 +169,6 @@ synchronized void stop(InputPortAudioStream slave) PortAudio.Pa_CloseStream(stream); stream = 0; started = false; - stopping = false; PortAudioManager.getInstance().stoppedInputPortAudioStream(this); } } @@ -207,30 +197,24 @@ public long getStream() * @return the bytes that a read from underlying stream. * @throws PortAudioException if an error occurs while reading. */ - public byte[] read() + public synchronized byte[] read() throws PortAudioException { - if(stopping) + if(!started) return new byte[0]; - synchronized(this) - { - if(!started) - return new byte[0]; - - byte[] bytebuff = new byte[PortAudioManager.NUM_SAMPLES*frameSize]; + byte[] bytebuff = new byte[PortAudioManager.NUM_SAMPLES*frameSize]; - synchronized(connectedToStreamSync) - { - PortAudio.Pa_ReadStream( - stream, bytebuff, PortAudioManager.NUM_SAMPLES); - } + synchronized(connectedToStreamSync) + { + PortAudio.Pa_ReadStream( + stream, bytebuff, PortAudioManager.NUM_SAMPLES); + } - for(InputPortAudioStream slave : slaves) - slave.setBuffer(bytebuff); + for(InputPortAudioStream slave : slaves) + slave.setBuffer(bytebuff); - return bytebuff; - } + return bytebuff; } /** @@ -260,13 +244,4 @@ public void setParams(OutputPortAudioStream out, deNoiseEnabled, echoCancelEnabled, frameSize, filterLength); } - - /** - * Inform that we will be stopping this stream. - * @param stopping the stopping to set - */ - public void setStopping(boolean stopping) - { - this.stopping = stopping; - } }