diff --git a/src/org/jitsi/impl/neomedia/control/AbstractControls.java b/src/org/jitsi/impl/neomedia/control/AbstractControls.java
index 87e03abd989d138c50ee1df7eea75c49c0280fda..e25d2daa082e2c3835e9e20ac24ce39a37bed505 100644
--- a/src/org/jitsi/impl/neomedia/control/AbstractControls.java
+++ b/src/org/jitsi/impl/neomedia/control/AbstractControls.java
@@ -15,7 +15,7 @@
  * implementers by requiring them to only implement
  * {@link Controls#getControls()}.
  *
- * @author Lubomir Marinov
+ * @author Lyubomir Marinov
  */
 public abstract class AbstractControls
     implements Controls
@@ -73,16 +73,111 @@ public static Object getControl(Controls controlsImpl, String controlType)
             catch (ClassNotFoundException cnfe)
             {
                 controlClass = null;
-                logger
-                    .warn(
+                logger.warn(
                         "Failed to find control class " + controlType,
                         cnfe);
             }
             if (controlClass != null)
+            {
                 for (Object control : controls)
+                {
                     if (controlClass.isInstance(control))
                         return control;
+                }
+            }
         }
         return null;
     }
+
+    /**
+     * Returns an instance of a specific <tt>Class</tt> which is either a
+     * control of a specific <tt>Controls</tt> implementation or the
+     * <tt>Controls</tt> implementation itself if it is an instance of the
+     * specified <tt>Class</tt>. The method is similar to
+     * {@link #getControl(Controls, String)} in querying the specified
+     * <tt>Controls</tt> implementation about a control of the specified
+     * <tt>Class</tt> but is different in looking at the type hierarchy of the
+     * <tt>Controls</tt> implementation for the specified <tt>Class</tt>.
+     *
+     * @param controlsImpl the <tt>Controls</tt> implementation to query
+     * @param controlType the runtime type of the instance to be returned
+     * @return an instance of the specified <tt>controlType</tt> if such an
+     * instance can be found among the controls of the specified
+     * <tt>controlsImpl</tt> or <tt>controlsImpl</tt> is an instance of the
+     * specified <tt>controlType</tt>; otherwise, <tt>null</tt>
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T queryInterface(
+            Controls controlsImpl,
+            Class<T> controlType)
+    {
+        T control;
+
+        if (controlsImpl == null)
+        {
+            control = null;
+        }
+        else
+        {
+            control = (T) controlsImpl.getControl(controlType.getName());
+            if ((control == null) && controlType.isInstance(controlsImpl))
+                control = (T) controlsImpl;
+        }
+        return control;
+    }
+
+    /**
+     * Returns an instance of a specific <tt>Class</tt> which is either a
+     * control of a specific <tt>Controls</tt> implementation or the
+     * <tt>Controls</tt> implementation itself if it is an instance of the
+     * specified <tt>Class</tt>. The method is similar to
+     * {@link #getControl(Controls, String)} in querying the specified
+     * <tt>Controls</tt> implementation about a control of the specified
+     * <tt>Class</tt> but is different in looking at the type hierarchy of the
+     * <tt>Controls</tt> implementation for the specified <tt>Class</tt>.
+     *
+     * @param controlsImpl the <tt>Controls</tt> implementation to query
+     * @param controlType the runtime type of the instance to be returned
+     * @return an instance of the specified <tt>controlType</tt> if such an
+     * instance can be found among the controls of the specified
+     * <tt>controlsImpl</tt> or <tt>controlsImpl</tt> is an instance of the
+     * specified <tt>controlType</tt>; otherwise, <tt>null</tt>
+     */
+    public static Object queryInterface(
+            Controls controlsImpl,
+            String controlType)
+    {
+        Object control;
+
+        if (controlsImpl == null)
+        {
+            control = null;
+        }
+        else
+        {
+            control = controlsImpl.getControl(controlType);
+            if (control == null)
+            {
+                Class<?> controlClass;
+
+                try
+                {
+                    controlClass = Class.forName(controlType);
+                }
+                catch (ClassNotFoundException cnfe)
+                {
+                    controlClass = null;
+                    logger.warn(
+                            "Failed to find control class " + controlType,
+                            cnfe);
+                }
+                if ((controlClass != null)
+                        && controlClass.isInstance(controlsImpl))
+                {
+                    control = controlsImpl;
+                }
+            }
+        }
+        return control;
+    }
 }
diff --git a/src/org/jitsi/impl/neomedia/device/MediaDeviceSession.java b/src/org/jitsi/impl/neomedia/device/MediaDeviceSession.java
index d24f1f9b9ca7e8612c2ae5d0ff17d33a3c9a0b09..a9a4a7944898842c01f1fef0e292700aa5c4a78b 100644
--- a/src/org/jitsi/impl/neomedia/device/MediaDeviceSession.java
+++ b/src/org/jitsi/impl/neomedia/device/MediaDeviceSession.java
@@ -18,6 +18,7 @@
 import javax.media.rtp.*;
 
 import org.jitsi.impl.neomedia.*;
+import org.jitsi.impl.neomedia.control.*;
 import org.jitsi.impl.neomedia.format.*;
 import org.jitsi.impl.neomedia.protocol.*;
 import org.jitsi.service.neomedia.*;
@@ -395,24 +396,36 @@ protected DataSource createCaptureDevice()
     {
         DataSource captureDevice = getDevice().createOutputDataSource();
 
-        if (!(captureDevice instanceof MuteDataSource))
+        if (captureDevice != null)
         {
-            // Try to enable muting.
-            if (captureDevice instanceof PushBufferDataSource)
-            {
-                captureDevice
-                    = new RewritablePushBufferDataSource(
-                            (PushBufferDataSource) captureDevice);
-            }
-            else if (captureDevice instanceof PullBufferDataSource)
+            MuteDataSource muteDataSource
+                = AbstractControls.queryInterface(
+                        captureDevice,
+                        MuteDataSource.class);
+
+            if (muteDataSource == null)
             {
-                captureDevice
-                    = new RewritablePullBufferDataSource(
-                            (PullBufferDataSource) captureDevice);
+                // Try to enable muting.
+                if (captureDevice instanceof PushBufferDataSource)
+                {
+                    captureDevice
+                        = new RewritablePushBufferDataSource(
+                                (PushBufferDataSource) captureDevice);
+                }
+                else if (captureDevice instanceof PullBufferDataSource)
+                {
+                    captureDevice
+                        = new RewritablePullBufferDataSource(
+                                (PullBufferDataSource) captureDevice);
+                }
+                muteDataSource
+                    = AbstractControls.queryInterface(
+                            captureDevice,
+                            MuteDataSource.class);
             }
+            if (muteDataSource != null)
+                muteDataSource.setMute(mute);
         }
-        if (captureDevice instanceof MuteDataSource)
-            ((MuteDataSource) captureDevice).setMute(mute);
 
         return captureDevice;
     }
@@ -1179,9 +1192,13 @@ public boolean isMute()
 
         if (captureDevice == null)
             return mute;
-        if (captureDevice instanceof MuteDataSource)
-            return ((MuteDataSource) captureDevice).isMute();
-        return false;
+
+        MuteDataSource muteDataSource
+            = AbstractControls.queryInterface(
+                    captureDevice,
+                    MuteDataSource.class);
+
+        return (muteDataSource == null) ? false : muteDataSource.isMute();
     }
 
     /**
@@ -1796,10 +1813,13 @@ public void setMute(boolean mute)
         {
             this.mute = mute;
 
-            DataSource captureDevice = this.captureDevice;
+            MuteDataSource muteDataSource
+                = AbstractControls.queryInterface(
+                        captureDevice,
+                        MuteDataSource.class);
 
-            if (captureDevice instanceof MuteDataSource)
-                ((MuteDataSource) captureDevice).setMute(this.mute);
+            if (muteDataSource != null)
+                muteDataSource.setMute(this.mute);
         }
     }
 
@@ -1810,10 +1830,13 @@ public void setMute(boolean mute)
      */
     public void addDTMF(DTMFInbandTone tone)
     {
-        DataSource captureDevice = this.captureDevice;
+        InbandDTMFDataSource inbandDTMFDataSource
+            = AbstractControls.queryInterface(
+                    captureDevice,
+                    InbandDTMFDataSource.class);
 
-        if (captureDevice instanceof InbandDTMFDataSource)
-            ((InbandDTMFDataSource) captureDevice).addDTMF(tone);
+        if (inbandDTMFDataSource != null)
+            inbandDTMFDataSource.addDTMF(tone);
     }
 
     /**
diff --git a/src/org/jitsi/impl/neomedia/protocol/RewritablePullBufferDataSource.java b/src/org/jitsi/impl/neomedia/protocol/RewritablePullBufferDataSource.java
index af5dd0b678d9c91011e44e212f9b7ee8487301e0..563dbab1e7df31d3325505084c535c47367018aa 100644
--- a/src/org/jitsi/impl/neomedia/protocol/RewritablePullBufferDataSource.java
+++ b/src/org/jitsi/impl/neomedia/protocol/RewritablePullBufferDataSource.java
@@ -12,6 +12,7 @@
 import javax.media.*;
 import javax.media.protocol.*;
 
+import org.jitsi.impl.neomedia.control.*;
 import org.jitsi.service.neomedia.*;
 
 /**
@@ -24,7 +25,7 @@
  * </p>
  *
  * @author Damian Minkov
- * @author Lubomir Marinov
+ * @author Lyubomir Marinov
  */
 public class RewritablePullBufferDataSource
     extends PullBufferDataSourceDelegate<PullBufferDataSource>
@@ -39,7 +40,8 @@ public class RewritablePullBufferDataSource
     /**
      * The tones to send via inband DTMF, if not empty.
      */
-    private LinkedList<DTMFInbandTone> tones = new LinkedList<DTMFInbandTone>();
+    private final LinkedList<DTMFInbandTone> tones
+        = new LinkedList<DTMFInbandTone>();
 
     /**
      * Initializes a new <tt>RewritablePullBufferDataSource</tt> instance which
@@ -106,6 +108,24 @@ public PullBufferDataSource getWrappedDataSource()
         return dataSource;
     }
 
+    /**
+     * {@inheritDoc}
+     *
+     * Overrides the super implementation to include the type hierarchy of the
+     * very wrapped <tt>dataSource</tt> instance into the search for the
+     * specified <tt>controlType</tt>. 
+     */
+    @Override
+    public Object getControl(String controlType)
+    {
+        /*
+         * The super implements a delegate so we can be sure that it delegates
+         * the invocation of Controls#getControl(String) to the wrapped
+         * dataSource.
+         */
+        return AbstractControls.queryInterface(dataSource, controlType);
+    }
+
     /**
      * Implements {@link PullBufferDataSource#getStreams()}. Wraps the streams
      * of the wrapped <tt>PullBufferDataSource</tt> into
diff --git a/src/org/jitsi/impl/neomedia/protocol/RewritablePushBufferDataSource.java b/src/org/jitsi/impl/neomedia/protocol/RewritablePushBufferDataSource.java
index e718f23f0d212777164311fc39e1d7ff44421a52..66ee434fb68e243c53d86a3df511005d8c2613aa 100644
--- a/src/org/jitsi/impl/neomedia/protocol/RewritablePushBufferDataSource.java
+++ b/src/org/jitsi/impl/neomedia/protocol/RewritablePushBufferDataSource.java
@@ -15,10 +15,8 @@
 import javax.media.format.*;
 import javax.media.protocol.*;
 
+import org.jitsi.impl.neomedia.control.*;
 import org.jitsi.service.neomedia.*;
-// disambiguation.
-// disambiguation.
-// disambiguation.
 
 /**
  * Implements a <tt>PushBufferDataSource</tt> wrapper which provides mute
@@ -45,7 +43,8 @@ public class RewritablePushBufferDataSource
     /**
      * The tones to send via inband DTMF, if not empty.
      */
-    private LinkedList<DTMFInbandTone> tones = new LinkedList<DTMFInbandTone>();
+    private final LinkedList<DTMFInbandTone> tones
+        = new LinkedList<DTMFInbandTone>();
 
     /**
      * Initializes a new <tt>RewritablePushBufferDataSource</tt> instance which
@@ -59,6 +58,24 @@ public RewritablePushBufferDataSource(PushBufferDataSource dataSource)
         super(dataSource);
     }
 
+    /**
+     * {@inheritDoc}
+     *
+     * Overrides the super implementation to include the type hierarchy of the
+     * very wrapped <tt>dataSource</tt> instance into the search for the
+     * specified <tt>controlType</tt>. 
+     */
+    @Override
+    public Object getControl(String controlType)
+    {
+        /*
+         * The super implements a delegate so we can be sure that it delegates
+         * the invocation of Controls#getControl(String) to the wrapped
+         * dataSource.
+         */
+        return AbstractControls.queryInterface(dataSource, controlType);
+    }
+
     /**
      * Implements {@link PushBufferDataSource#getStreams()}. Wraps the streams
      * of the wrapped <tt>PushBufferDataSource</tt> into