diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java b/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
index 7bba7863b..c53c077a2 100644
--- a/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
@@ -136,6 +136,13 @@ public class MediaStreamImpl
*/
private String localSourceID = null;
+ /**
+ * The indicator which determines whether this MediaStream is set
+ * to transmit "silence" instead of the actual media fed from its
+ * MediaDevice.
+ */
+ private boolean mute = false;
+
/**
* Initializes a new MediaStreamImpl instance which will use the
* specified MediaDevice for both capture and playback of media
@@ -586,12 +593,9 @@ private RTPManager getRTPManager()
*/
public boolean isMute()
{
- MediaDevice device = getDevice();
+ MediaDeviceSession deviceSession = getDeviceSession();
- return
- (device instanceof MediaDeviceImpl)
- ? ((MediaDeviceImpl) device).isMute()
- : false;
+ return (deviceSession == null) ? mute : deviceSession.isMute();
}
/**
@@ -716,6 +720,7 @@ public void setDevice(MediaDevice device)
if (deviceSession != null)
{
+ deviceSession.setMute(mute);
deviceSession.start(startedDirection);
synchronized (receiveStreams)
@@ -806,12 +811,15 @@ public void setFormat(MediaFormat format)
*/
public void setMute(boolean mute)
{
- MediaDevice device = getDevice();
+ if (this.mute != mute)
+ {
+ this.mute = mute;
- if (device instanceof MediaDeviceImpl)
- ((MediaDeviceImpl) device).setMute(mute);
- else
- throw new IllegalStateException("device");
+ MediaDeviceSession deviceSession = getDeviceSession();
+
+ if (deviceSession != null)
+ deviceSession.setMute(this.mute);
+ }
}
/**
diff --git a/src/net/java/sip/communicator/impl/neomedia/conference/AudioMixer.java b/src/net/java/sip/communicator/impl/neomedia/conference/AudioMixer.java
index 435e10057..11bce3fab 100644
--- a/src/net/java/sip/communicator/impl/neomedia/conference/AudioMixer.java
+++ b/src/net/java/sip/communicator/impl/neomedia/conference/AudioMixer.java
@@ -263,7 +263,23 @@ void connect()
{
if (connected == 0)
for (InputDataSourceDesc inputDataSourceDesc : inputDataSources)
- inputDataSourceDesc.getEffectiveInputDataSource().connect();
+ try
+ {
+ inputDataSourceDesc
+ .getEffectiveInputDataSource().connect();
+ }
+ catch (IOException ioe)
+ {
+ logger
+ .error(
+ "Failed to connect to inputDataSource "
+ + MediaStreamImpl
+ .toString(
+ inputDataSourceDesc
+ .inputDataSource),
+ ioe);
+ throw ioe;
+ }
connected++;
}
diff --git a/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java b/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java
index 5f609e7ca..907cfe77e 100644
--- a/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java
+++ b/src/net/java/sip/communicator/impl/neomedia/device/AudioMixerMediaDevice.java
@@ -109,7 +109,7 @@ public synchronized MediaDeviceSession createSession()
private AudioMixer getAudioMixer()
{
if (audioMixer == null)
- audioMixer = new AudioMixer(device.getCaptureDevice())
+ audioMixer = new AudioMixer(device.createCaptureDevice())
{
@Override
protected void readCaptureDeviceStream(
diff --git a/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceImpl.java b/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceImpl.java
index dc48fbc9e..e08136986 100644
--- a/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceImpl.java
@@ -38,23 +38,11 @@ public class MediaDeviceImpl
private static final Logger logger
= Logger.getLogger(MediaDeviceImpl.class);
- /**
- * The JMF CaptureDevice this instance wraps and provides an
- * implementation of MediaDevice for.
- */
- private CaptureDevice captureDevice;
-
/**
* The CaptureDeviceInfo of {@link #captureDevice}.
*/
private CaptureDeviceInfo captureDeviceInfo;
- /**
- * The indicator which determines whether {@link DataSource#connect()} has
- * been successfully executed on {@link #captureDevice}.
- */
- private boolean captureDeviceIsConnected;
-
/**
* The MediaType of this instance and the CaptureDevice
* that it wraps.
@@ -70,32 +58,10 @@ public class MediaDeviceImpl
*/
public MediaDeviceImpl(MediaType mediaType)
{
- this.captureDevice = null;
this.captureDeviceInfo = null;
this.mediaType = mediaType;
}
- /**
- * Initializes a new MediaDeviceImpl instance which is to provide
- * an implementation of MediaDevice for a specific
- * CaptureDevice with a specific MediaType.
- *
- * @param captureDevice the JMF CaptureDevice the new instance is
- * to provide an implementation of MediaDevice for
- * @param mediaType the MediaType of the new instance
- */
- public MediaDeviceImpl(CaptureDevice captureDevice, MediaType mediaType)
- {
- if (captureDevice == null)
- throw new NullPointerException("captureDevice");
- if (mediaType == null)
- throw new NullPointerException("mediaType");
-
- this.mediaType = mediaType;
-
- setCaptureDevice(captureDevice);
- }
-
/**
* Initializes a new MediaDeviceImpl instance which is to provide
* an implementation of MediaDevice for a CaptureDevice
@@ -116,30 +82,60 @@ public MediaDeviceImpl(
if (mediaType == null)
throw new NullPointerException("mediaType");
- this.captureDevice = null;
this.captureDeviceInfo = captureDeviceInfo;
this.mediaType = mediaType;
}
/**
- * Notifies this instance that its captureDevice (the JMF
- * CaptureDevice this instance wraps and provides an implementation
- * of MediaDevice for) property has changed its value from
- * oldValue to newValue. Allows extenders to override in
- * order to perform additional processing of the new captureDevice
- * once it is clear that it is set into this instance.
+ * Creates the JMF CaptureDevice this instance represents and
+ * provides an implementation of MediaDevice for.
*
- * @param oldValue the JMF CaptureDevice which was the value of the
- * captureDevice property of this instance before newValue
- * was set
- * @param newValue the JMF CaptureDevice which is the value of the
- * captureDevice property of this instance and which replaced
- * oldValue
+ * @return the JMF CaptureDevice this instance represents and
+ * provides an implementation of MediaDevice for; null
+ * if the creation fails
*/
- protected void captureDeviceChanged(
- CaptureDevice oldValue,
- CaptureDevice newValue)
+ CaptureDevice createCaptureDevice()
{
+ CaptureDevice captureDevice = null;
+
+ if (getDirection().allowsSending())
+ {
+ Throwable exception = null;
+
+ try
+ {
+ captureDevice
+ = (CaptureDevice)
+ Manager
+ .createDataSource(captureDeviceInfo.getLocator());
+ }
+ catch (IOException ioe)
+ {
+ // TODO
+ exception = ioe;
+ }
+ catch (NoDataSourceException ndse)
+ {
+ // TODO
+ exception = ndse;
+ }
+
+ if (exception != null)
+ logger
+ .error(
+ "Failed to create CaptureDevice"
+ + "from CaptureDeviceInfo "
+ + captureDeviceInfo,
+ exception);
+ else
+ {
+ // Try to enable tracing on captureDevice.
+ if (logger.isTraceEnabled())
+ captureDevice
+ = createTracingCaptureDevice(captureDevice, logger);
+ }
+ }
+ return captureDevice;
}
/**
@@ -154,7 +150,7 @@ DataSource createOutputDataSource()
{
return
getDirection().allowsSending()
- ? (DataSource) getConnectedCaptureDevice()
+ ? (DataSource) createCaptureDevice()
: null;
}
@@ -236,79 +232,6 @@ public void stop()
return captureDevice;
}
- /**
- * Gets the JMF CaptureDevice this instance wraps and provides an
- * implementation of MediaDevice for.
- *
- * @return the JMF CaptureDevice this instance wraps and provides
- * an implementation of MediaDevice for
- */
- public CaptureDevice getCaptureDevice()
- {
- return getCaptureDevice(true);
- }
-
- /**
- * Gets the JMF CaptureDevice this instance wraps and provides an
- * implementation of MediaDevice for and, optionally, creates it if
- * it does not exist yet.
- *
- * @param create true to create the CaptureDevice this
- * instance provides an implementation of MediaDevice for it it
- * does not exist yet; false to not create it and return
- * null if it does not exist yet
- * @return the JMF CaptureDevice this instance wraps and provides
- * an implementation of MediaDevice for if it exists or
- * create is true and its creation succeeds; null
- * if it does not exist yet and create is false or its
- * creation fails
- */
- protected CaptureDevice getCaptureDevice(boolean create)
- {
- if (getDirection().allowsSending() && (captureDevice == null) && create)
- {
- CaptureDevice captureDevice = null;
- Throwable exception = null;
-
- try
- {
- captureDevice
- = (CaptureDevice)
- Manager
- .createDataSource(captureDeviceInfo.getLocator());
- }
- catch (IOException ioe)
- {
- // TODO
- exception = ioe;
- }
- catch (NoDataSourceException ndse)
- {
- // TODO
- exception = ndse;
- }
-
- if (exception != null)
- logger
- .error(
- "Failed to create CaptureDevice DataSource "
- + "from CaptureDeviceInfo "
- + captureDeviceInfo,
- exception);
- else
- {
-
- // Try to enable tracing on captureDevice.
- if (logger.isTraceEnabled())
- captureDevice
- = createTracingCaptureDevice(captureDevice, logger);
-
- setCaptureDevice(captureDevice);
- }
- }
- return captureDevice;
- }
-
/**
* Gets the CaptureDeviceInfo of the JMF CaptureDevice
* represented by this instance.
@@ -321,83 +244,6 @@ public CaptureDeviceInfo getCaptureDeviceInfo()
return captureDeviceInfo;
}
- /**
- * Gets the JMF CaptureDevice this instance wraps and provides an
- * implementation of MediaDevice for in a connected state. If the
- * CaptureDevice is not connected to yet, first tries to connect to
- * it. Returns null if this instance has failed to create a
- * CaptureDevice instance or to connect to it.
- *
- * @return the JMF CaptureDevice this instance wraps and provides
- * an implementation of MediaDevice for in a connected state;
- * null if this instance has failed to create a
- * CaptureDevice instance or to connect to it
- */
- private CaptureDevice getConnectedCaptureDevice()
- {
- CaptureDevice captureDevice = getCaptureDevice();
-
- if ((captureDevice != null) && !captureDeviceIsConnected)
- {
- Throwable exception = null;
-
- try
- {
- captureDevice.connect();
- }
- catch (IOException ioe)
- {
- // TODO
- exception = ioe;
- }
- catch (NullPointerException npe)
- {
- /*
- * TODO The old media says it happens when the operating system
- * does not support the operation.
- */
- exception = npe;
- }
-
- if (exception == null)
- {
- captureDeviceIsConnected = true;
-
- /*
- * 1. Changing buffer size. The default buffer size (for
- * javasound) is 125 milliseconds - 1/8 sec. On MacOS this leads
- * to an exception and no audio capture. A value of 30 for the
- * buffer fixes the problem and is OK when using some pstn
- * gateways.
- *
- * 2. Changing to 60. When it is 30 there are some issues with
- * asterisk and nat (we don't start to send stream and so
- * asterisk rtp part doesn't notice that we are behind nat)
- *
- * 3. Do not set buffer length on linux as it completely breaks
- * audio capture.
- */
- String osName = System.getProperty("os.name");
-
- if ((osName == null) || !osName.toLowerCase().contains("linux"))
- {
- Control bufferControl
- = (Control)
- ((DataSource) captureDevice)
- .getControl(
- "javax.media.control.BufferControl");
-
- if (bufferControl != null)
- ((BufferControl) bufferControl)
- .setBufferLength(60); // in milliseconds
- }
- }
- else
- captureDevice = null;
- }
- return captureDevice;
- }
-
/**
* Returns the MediaDirection supported by this device.
*
@@ -409,19 +255,13 @@ private CaptureDevice getConnectedCaptureDevice()
*/
public MediaDirection getDirection()
{
- if ((captureDeviceInfo != null) || (captureDevice != null))
+ if (captureDeviceInfo != null)
return MediaDirection.SENDRECV;
else
- {
- /*
- * If there is no audio CaptureDevice, then even play back is not
- * possible.
- */
return
MediaType.AUDIO.equals(getMediaType())
? MediaDirection.INACTIVE
: MediaDirection.RECVONLY;
- }
}
/**
@@ -434,7 +274,7 @@ public MediaDirection getDirection()
*/
public MediaFormat getFormat()
{
- CaptureDevice captureDevice = getCaptureDevice();
+ CaptureDevice captureDevice = createCaptureDevice();
if (captureDevice != null)
{
@@ -488,85 +328,6 @@ public List getSupportedFormats()
return supportedFormats;
}
- /**
- * Determines whether this MediaDevice will provide silence instead
- * of actual captured data next time it is read.
- *
- * @return true if this MediaDevice will provide silence
- * instead of actual captured data next time it is read; false,
- * otherwise
- */
- public boolean isMute()
- {
- CaptureDevice captureDevice = getCaptureDevice(false);
-
- if (captureDevice instanceof MutePushBufferDataSource)
- return ((MutePushBufferDataSource) captureDevice).isMute();
-
- /*
- * If there is no underlying CaptureDevice, this instance is mute
- * because it cannot capture any media.
- */
- return !getDirection().allowsSending();
- }
-
- /**
- * Sets the JMF CaptureDevice this instance wraps and provides a
- * MediaDevice implementation for. Allows extenders to override in
- * order to customize captureDevice including to replace it before
- * it is set into this instance.
- *
- * @param captureDevice the JMF CaptureDevice this instance is to
- * wrap and provide a MediaDevice implementation for
- */
- protected void setCaptureDevice(CaptureDevice captureDevice)
- {
- /*
- * Translate PullBufferDataSource into PushBufferDataSource because
- * other functionality such as MutePushBufferDataSource may depend on
- * it.
- */
-// if (captureDevice instanceof PullBufferDataSource)
-// captureDevice
-// = new PushBufferDataSourceAdapter(
-// (PullBufferDataSource) captureDevice);
-
- // Try to enable mute support on the specified CaptureDevice.
- if (captureDevice instanceof PushBufferDataSource)
- captureDevice
- = new MutePushBufferDataSource(
- (PushBufferDataSource) captureDevice);
-
- if (this.captureDevice != captureDevice)
- {
- CaptureDevice oldValue = this.captureDevice;
-
- this.captureDevice = captureDevice;
- this.captureDeviceInfo = captureDevice.getCaptureDeviceInfo();
-
- CaptureDevice newValue = captureDevice;
-
- captureDeviceChanged(oldValue, newValue);
- }
- }
-
- /**
- * Sets the indicator which determines whether this MediaDevice
- * will start providing silence instead of actual captured data next time it
- * is read.
- *
- * @param mute true to have this MediaDevice start
- * providing silence instead of actual captured data next time it is read;
- * otherwise, false
- */
- public void setMute(boolean mute)
- {
- CaptureDevice captureDevice = getCaptureDevice();
-
- if (captureDevice instanceof MutePushBufferDataSource)
- ((MutePushBufferDataSource) captureDevice).setMute(mute);
- }
-
/**
* Gets a human-readable String representation of this instance.
*
diff --git a/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java b/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java
index f663c83a3..96834341e 100644
--- a/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java
+++ b/src/net/java/sip/communicator/impl/neomedia/device/MediaDeviceSession.java
@@ -19,6 +19,7 @@
import net.java.sip.communicator.impl.neomedia.*;
import net.java.sip.communicator.impl.neomedia.codec.audio.*;
import net.java.sip.communicator.impl.neomedia.format.*;
+import net.java.sip.communicator.impl.neomedia.protocol.*;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.neomedia.device.*;
import net.java.sip.communicator.service.neomedia.event.*;
@@ -76,6 +77,13 @@ public class MediaDeviceSession
*/
private Format format;
+ /**
+ * The indicator which determines whether this MediaDeviceSession
+ * is set to output "silence" instead of the actual media captured from
+ * {@link #captureDevice}.
+ */
+ private boolean mute = false;
+
/**
* The ControllerListener which listens to the Player
* instances in {@link #players} for ControllerEvents.
@@ -464,7 +472,20 @@ private void closeProcessor()
*/
protected DataSource createCaptureDevice()
{
- return getDevice().createOutputDataSource();
+ DataSource captureDevice = getDevice().createOutputDataSource();
+
+ // Try to enable muting.
+ if (captureDevice instanceof PushBufferDataSource)
+ {
+ MutePushBufferDataSource mutePushBufferDataSource
+ = new MutePushBufferDataSource(
+ (PushBufferDataSource) captureDevice);
+
+ mutePushBufferDataSource.setMute(mute);
+ captureDevice = mutePushBufferDataSource;
+ }
+
+ return captureDevice;
}
/**
@@ -888,6 +909,26 @@ public List getSupportedFormats()
return supportedMediaFormats;
}
+ /**
+ * Determines whether this MediaDeviceSession is set to output
+ * "silence" instead of the actual media fed from its
+ * CaptureDevice.
+ *
+ * @return true if this MediaDeviceSession is set to
+ * output "silence" instead of the actual media fed from its
+ * CaptureDevice; otherwise, false
+ */
+ public boolean isMute()
+ {
+ DataSource captureDevice = this.captureDevice;
+
+ if (captureDevice == null)
+ return mute;
+ if (captureDevice instanceof MutePushBufferDataSource)
+ return ((MutePushBufferDataSource) captureDevice).isMute();
+ return false;
+ }
+
/**
* Gets notified about ControllerEvents generated by
* {@link #processor}.
@@ -1160,6 +1201,28 @@ else if (logger.isTraceEnabled())
}
}
+ /**
+ * Sets the indicator which determines whether this
+ * MediaDeviceSession is set to output "silence" instead of the
+ * actual media fed from its CaptureDevice.
+ *
+ * @param mute true to set this MediaDeviceSession to
+ * output "silence" instead of the actual media fed from its
+ * CaptureDevice; otherwise, false
+ */
+ public void setMute(boolean mute)
+ {
+ if (this.mute != mute)
+ {
+ this.mute = mute;
+
+ DataSource captureDevice = this.captureDevice;
+
+ if (captureDevice instanceof MutePushBufferDataSource)
+ ((MutePushBufferDataSource) captureDevice).setMute(this.mute);
+ }
+ }
+
/**
* Sets the JMF Processor which is to transcode
* {@link #captureDevice} into the format of this instance.
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
index 25af0349e..0ff94cd5c 100644
--- 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
@@ -14,8 +14,10 @@
import javax.media.format.*;
import javax.media.protocol.*;
-import net.java.sip.communicator.util.*;
+import net.java.sip.communicator.impl.neomedia.*;
+import net.java.sip.communicator.impl.neomedia.control.*;
import net.java.sip.communicator.impl.neomedia.portaudio.*;
+import net.java.sip.communicator.util.*;
/**
* Implements DataSource and CaptureDevice for PortAudio.
@@ -83,6 +85,8 @@ public void connect()
return;
connected = true;
+ if (logger.isTraceEnabled())
+ logger.trace("Connected " + MediaStreamImpl.toString(this));
}
/**
@@ -106,6 +110,8 @@ public void disconnect()
}
connected = false;
+ if (logger.isTraceEnabled())
+ logger.trace("Disconnected " + MediaStreamImpl.toString(this));
}
/**
@@ -274,6 +280,8 @@ public void start()
}
started = true;
+ if (logger.isTraceEnabled())
+ logger.trace("Started " + MediaStreamImpl.toString(this));
}
/**
@@ -299,6 +307,8 @@ public void stop()
}
started = false;
+ if (logger.isTraceEnabled())
+ logger.trace("Stopped " + MediaStreamImpl.toString(this));
}
/**
@@ -307,30 +317,9 @@ public void stop()
* important because, for example, AudioMixer will ask for it.
*/
private class FormatControlImpl
- implements FormatControl
+ extends AbstractFormatControl
{
- /**
- * 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()}.
*
@@ -352,67 +341,5 @@ 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;
- }
}
}