diff --git a/src/org/jitsi/impl/neomedia/device/AudioSystem.java b/src/org/jitsi/impl/neomedia/device/AudioSystem.java
index 687044839df688d701a97c0b0f51635b28e864bf..8a1ac516014f66628752c343e8669f15ff310d5d 100644
--- a/src/org/jitsi/impl/neomedia/device/AudioSystem.java
+++ b/src/org/jitsi/impl/neomedia/device/AudioSystem.java
@@ -217,7 +217,7 @@ protected void setPlaybackDevices(
             List<ExtendedCaptureDeviceInfo> activePlaybackDevices)
     {
         devices[PLAYBACK_INDEX].setActiveDevices(activePlaybackDevices);
-        // The active notify device list is a copy of the playback one.
+        // The notify devices are the same as the playback devices.
         devices[NOTIFY_INDEX].setActiveDevices(activePlaybackDevices);
     }
 
@@ -282,7 +282,7 @@ protected void postInitialize()
 
     /**
      * Sets the device lists after the different audio systems (PortAudio,
-     * PulseAudio, etc) have finished to detects the devices.
+     * PulseAudio, etc) have finished detecting their devices.
      *
      * @param index The index corresponding to a specific device kind:
      * capture/notify/playback.
@@ -357,8 +357,8 @@ public InputStream getAudioInputStream(String uri)
                 url = new URL(uri);
             }
 
-            audioStream = javax.sound.sampled.AudioSystem
-                .getAudioInputStream(url);
+            audioStream
+                = javax.sound.sampled.AudioSystem.getAudioInputStream(url);
         }
         catch (MalformedURLException e)
         {
diff --git a/src/org/jitsi/impl/neomedia/device/CaptureDevices.java b/src/org/jitsi/impl/neomedia/device/CaptureDevices.java
index 422b1adddc47064f8b7a8b58c43d0327ef61ead3..6e58099edc124bc1340b47782c5e12d7e8bb79ad 100644
--- a/src/org/jitsi/impl/neomedia/device/CaptureDevices.java
+++ b/src/org/jitsi/impl/neomedia/device/CaptureDevices.java
@@ -51,24 +51,24 @@ public CaptureDevices(AudioSystem audioSystem)
      */
     public List<ExtendedCaptureDeviceInfo> getDevices()
     {
-        Format[] formats;
-        Format format = new AudioFormat(AudioFormat.LINEAR, -1, 16, -1);
         List<ExtendedCaptureDeviceInfo> devices = null;
 
-        if(this.activeCaptureDevices != null)
+        if(activeCaptureDevices != null)
         {
-            devices = new ArrayList<ExtendedCaptureDeviceInfo>(
-                    this.activeCaptureDevices.size());
+            devices
+                = new ArrayList<ExtendedCaptureDeviceInfo>(
+                        activeCaptureDevices.size());
 
-            for(ExtendedCaptureDeviceInfo device: this.activeCaptureDevices)
+            Format format = new AudioFormat(AudioFormat.LINEAR, -1, 16, -1);
+
+            for(ExtendedCaptureDeviceInfo device: activeCaptureDevices)
             {
-                formats = device.getFormats();
-                for(int i = 0; i < formats.length; ++i)
+                for(Format deviceFormat : device.getFormats())
                 {
-                    if(formats[i].matches(format))
+                    if(deviceFormat.matches(format))
                     {
                         devices.add(device);
-                        i = formats.length;
+                        break;
                     }
                 }
             }
@@ -77,6 +77,16 @@ public List<ExtendedCaptureDeviceInfo> getDevices()
         return devices;
     }
 
+    /**
+     * Returns the property of the capture devices.
+     *
+     * @return The property of the capture devices.
+     */
+    protected String getPropDevice()
+    {
+        return PROP_DEVICE;
+    }
+
     /**
      * Sets the list of the active devices.
      *
@@ -106,18 +116,8 @@ public void setActiveDevices(List<ExtendedCaptureDeviceInfo> activeDevices)
             }
         }
 
-        this.activeCaptureDevices = (activeDevices == null)
+        activeCaptureDevices = (activeDevices == null)
                 ? null
                 : new ArrayList<ExtendedCaptureDeviceInfo>(activeDevices);
     }
-
-    /**
-     * Returns the property of the capture devices.
-     *
-     * @return The property of the capture devices.
-     */
-    protected String getPropDevice()
-    {
-        return PROP_DEVICE;
-    }
 }
diff --git a/src/org/jitsi/impl/neomedia/device/DeviceSystem.java b/src/org/jitsi/impl/neomedia/device/DeviceSystem.java
index 8c957c3f4377844170aed2e286b8e00a9296680e..48f7604811cb19eb2aa6a3673b3cff116de28462 100644
--- a/src/org/jitsi/impl/neomedia/device/DeviceSystem.java
+++ b/src/org/jitsi/impl/neomedia/device/DeviceSystem.java
@@ -41,6 +41,12 @@ public abstract class DeviceSystem
      */
     private static final Logger logger = Logger.getLogger(DeviceSystem.class);
 
+    /**
+     * The list of <tt>DeviceSystem</tt>s which have been initialized.
+     */
+    private static List<DeviceSystem> deviceSystems
+        = new LinkedList<DeviceSystem>();
+
     /**
      * The constant/flag (to be) returned by {@link #getFeatures()} in order to
      * indicate that the respective <tt>DeviceSystem</tt> supports invoking its
@@ -63,23 +69,30 @@ public abstract class DeviceSystem
     public static final String PROP_DEVICES = "devices";
 
     /**
-     * The list of devices connected at the last preInitialize.
+     * The list of devices connected at the last postInitialize.
      */
-    private static Vector<CaptureDeviceInfo> propertyChangeOldDevices
+    private static Vector<CaptureDeviceInfo> propertyChangeNewDevices
         = new Vector<CaptureDeviceInfo>();
 
     /**
-     * The list of devices connected at the last postInitialize.
+     * The list of devices connected at the last preInitialize.
      */
-    private static Vector<CaptureDeviceInfo> propertyChangeNewDevices
+    private static Vector<CaptureDeviceInfo> propertyChangeOldDevices
         = new Vector<CaptureDeviceInfo>();
 
     /**
-     * The list of <tt>DeviceSystem</tt>s which have been initialized.
+     * Returns a <tt>List</tt> of <tt>CaptureDeviceInfo</tt>s which are elements
+     * of a specific <tt>List</tt> of <tt>CaptureDeviceInfo</tt>s and have a
+     * specific <tt>MediaLocator</tt> protocol.
+     *
+     * @param deviceList the <tt>List</tt> of <tt>CaptureDeviceInfo</tt> which
+     * are to be filtered based on the specified <tt>MediaLocator</tt> protocol
+     * @param locatorProtocol the protocol of the <tt>MediaLocator</tt>s of the
+     * <tt>CaptureDeviceInfo</tt>s which are to be returned
+     * @return a <tt>List</tt> of <tt>CaptureDeviceInfo</tt>s which are elements
+     * of the specified <tt>deviceList</tt> and have the specified
+     * <tt>locatorProtocol</tt>
      */
-    private static List<DeviceSystem> deviceSystems
-        = new LinkedList<DeviceSystem>();
-
     protected static List<CaptureDeviceInfo> filterDeviceListByLocatorProtocol(
             List<CaptureDeviceInfo> deviceList,
             String locatorProtocol)
@@ -388,14 +401,72 @@ public Renderer createRenderer(boolean playback)
         return null;
     }
 
+    /**
+     * Invoked by {@link #initialize()} to perform the very logic of the
+     * initialization of this <tt>DeviceSystem</tt>. This instance has been
+     * prepared for initialization by an earlier call to
+     * {@link #preInitialize()} and the initialization will be completed with a
+     * subsequent call to {@link #postInitialize()}.
+     *
+     * @throws Exception if an error occurs during the initialization of this
+     * instance. The initialization of this instance will be completed with a
+     * subsequent call to <tt>postInitialize()</tt> regardless of any
+     * <tt>Exception</tt> thrown by <tt>doInitialize()</tt>.
+     */
     protected abstract void doInitialize()
         throws Exception;
 
+    /**
+     * Gets the flags indicating the optional features supported by this
+     * <tt>DeviceSystem</tt>.
+     *
+     * @return the flags indicating the optional features supported by this
+     * <tt>DeviceSystem</tt>. The possible flags are among the
+     * <tt>FEATURE_XXX</tt> constants defined by the <tt>DeviceSystem</tt> class
+     * and its extenders.
+     */
     public final int getFeatures()
     {
         return features;
     }
 
+    /**
+     * Returns the format depending on the media type: AudioFormat for AUDIO,
+     * VideoFormat for VIDEO. Otherwise, returns null.
+     *
+     * @return The format depending on the media type: AudioFormat for AUDIO,
+     * VideoFormat for VIDEO. Otherwise, returns null.
+     */
+    public Format getFormat()
+    {
+        Format format = null;
+
+        switch (getMediaType())
+        {
+        case AUDIO:
+            format = new AudioFormat(null);
+            break;
+        case VIDEO:
+            format = new VideoFormat(null);
+            break;
+        default:
+            format = null;
+            break;
+        }
+
+        return format;
+    }
+
+    /**
+     * Gets the protocol of the <tt>MediaLocator</tt> of the
+     * <tt>CaptureDeviceInfo</tt>s (to be) registered (with FMJ) by this
+     * <tt>DeviceSystem</tt>. The protocol is a unique identifier of a
+     * <tt>DeviceSystem</tt>.
+     *
+     * @return the protocol of the <tt>MediaLocator</tt> of the
+     * <tt>CaptureDeviceInfo</tt>s (to be) registered (with FMJ) by this
+     * <tt>DeviceSystem</tt>
+     */
     public final String getLocatorProtocol()
     {
         return locatorProtocol;
@@ -406,11 +477,32 @@ public final MediaType getMediaType()
         return mediaType;
     }
 
+    /**
+     * Gets the name of the class which implements the <tt>Renderer</tt>
+     * interface to render media on a playback or notification device associated
+     * with this <tt>DeviceSystem</tt>. Invoked by
+     * {@link #createRenderer(boolean)}.
+     * 
+     * @return the name of the class which implements the <tt>Renderer</tt>
+     * interface to render media on a playback or notification device associated
+     * with this <tt>DeviceSystem</tt> or <tt>null</tt> if no <tt>Renderer</tt>
+     * instance is to be created by the <tt>DeviceSystem</tt> implementation or
+     * <tt>createRenderer(boolean) is overridden.
+     */
     protected String getRendererClassName()
     {
         return null;
     }
 
+    /**
+     * Initializes this <tt>DeviceSystem</tt> i.e. represents the native/system
+     * devices in the terms of the application so that they may be utilized. For
+     * example, the capture devices are represented as
+     * <tt>CaptureDeviceInfo</tt> instances registered with FMJ.
+     *
+     * @throws Exception if an error occurs during the initialization of this
+     * <tt>DeviceSystem</tt>
+     */
     protected final void initialize()
         throws Exception
     {
@@ -435,7 +527,7 @@ protected final void initialize()
      */
     protected void postInitialize()
     {
-        Format format = this.getFormat();
+        Format format = getFormat();
 
         if (format != null)
         {
@@ -444,7 +536,7 @@ protected void postInitialize()
             propertyChangeNewDevices.addAll(
                 CaptureDeviceManager.getDeviceList(format));
 
-            // Compares the previous conencted device list with the current one,
+            // Compares the previous connected device list with the current one
             // in order to detect new connected or disconnected devices.
             for(int i = 0; i < propertyChangeOldDevices.size(); ++i)
             {
@@ -478,7 +570,7 @@ protected void postInitialize()
      */
     protected void preInitialize()
     {
-        Format format = this.getFormat();
+        Format format = getFormat();
 
         if (format != null)
         {
@@ -535,31 +627,4 @@ public String toString()
     {
         return getLocatorProtocol();
     }
-
-    /**
-     * Returns the format depending on the media type: AudioFormat for AUDIO,
-     * VideoFormat for VIDEO. Otherwise, returns null.
-     *
-     * @return The format depending on the media type: AudioFormat for AUDIO,
-     * VideoFormat for VIDEO. Otherwise, returns null.
-     */
-    public Format getFormat()
-    {
-        Format format = null;
-
-        switch (getMediaType())
-        {
-        case AUDIO:
-            format = new AudioFormat(null);
-            break;
-        case VIDEO:
-            format = new VideoFormat(null);
-            break;
-        default:
-            format = null;
-            break;
-        }
-
-        return format;
-    }
 }
diff --git a/src/org/jitsi/impl/neomedia/device/Devices.java b/src/org/jitsi/impl/neomedia/device/Devices.java
index f63cae7e900e285e0818e87efa3e4ee7e29fc70a..56ab17b8bad9a5451c8f9ffa72f16e714b5278da 100644
--- a/src/org/jitsi/impl/neomedia/device/Devices.java
+++ b/src/org/jitsi/impl/neomedia/device/Devices.java
@@ -75,7 +75,7 @@ public ExtendedCaptureDeviceInfo getDevice(
                     // Adds the device in the preference list (to the end of the
                     // list, but the save device will push it to the top of
                     // active devices).
-                    this.saveDevice(
+                    saveDevice(
                             locator,
                             property,
                             activeDevice,
@@ -88,20 +88,20 @@ public ExtendedCaptureDeviceInfo getDevice(
             // in the preferences.
             synchronized(devicePreferences)
             {
-                for(int i = 0; i < devicePreferences.size(); ++i)
+                for(String devicePreference : devicePreferences)
                 {
                     for(ExtendedCaptureDeviceInfo activeDevice : activeDevices)
                     {
                         // If we have found the "preferred" device among active
                         // device.
-                        if(devicePreferences.get(i).equals(
-                                    activeDevice.getIdentifier()))
+                        if(devicePreference.equals(
+                                activeDevice.getIdentifier()))
                         {
                             return activeDevice;
                         }
                         // If the "none" device is the "preferred" device among
                         // "active" device.
-                        else if(devicePreferences.get(i).equals(
+                        else if(devicePreference.equals(
                                     NoneAudioSystem.LOCATOR_PROTOCOL))
                         {
                             return null;
@@ -211,14 +211,14 @@ private void saveDevice(
         }
 
         // Sorts the user preferences to put the selected device on top.
-        this.addToDevicePreferences(
+        addToDevicePreferences(
                 locator,
                 activeDevices,
                 selectedDeviceIdentifier,
                 isSelected);
 
         // Saves the user preferences.
-        this.writeDevicePreferences(locator, property);
+        writeDevicePreferences(locator, property);
     }
 
     /**
@@ -253,8 +253,7 @@ public void setDevice(
             }
             this.device = device;
 
-            this.audioSystem
-                .propertyChange(getPropDevice(), oldValue, this.device);
+            audioSystem.propertyChange(getPropDevice(), oldValue, this.device);
         }
     }
 
@@ -394,7 +393,8 @@ private void writeDevicePreferences(String locator, String property)
                     + "." + property
                     + "_list";
 
-            StringBuffer value = new StringBuffer("[\"");
+            StringBuilder value = new StringBuilder("[\"");
+
             synchronized(devicePreferences)
             {
                 if(devicePreferences.size() > 0)
@@ -402,11 +402,12 @@ private void writeDevicePreferences(String locator, String property)
                     value.append(devicePreferences.get(0));
                     for(int i = 1; i < devicePreferences.size(); ++i)
                     {
-                        value.append("\", \"" + devicePreferences.get(i));
+                        value.append("\", \"").append(devicePreferences.get(i));
                     }
                 }
             }
             value.append("\"]");
+
             cfg.setProperty(property, value.toString());
         }
     }
diff --git a/src/org/jitsi/impl/neomedia/device/ExtendedCaptureDeviceInfo.java b/src/org/jitsi/impl/neomedia/device/ExtendedCaptureDeviceInfo.java
index abad36387492608227cf23d060dd9f308e6359fa..7a3f611045ae7d88f8d4aa8ae920cd057df2f0c7 100644
--- a/src/org/jitsi/impl/neomedia/device/ExtendedCaptureDeviceInfo.java
+++ b/src/org/jitsi/impl/neomedia/device/ExtendedCaptureDeviceInfo.java
@@ -18,14 +18,14 @@ public class ExtendedCaptureDeviceInfo
     extends CaptureDeviceInfo
 {
     /**
-     * The device UID (unique identifier).
+     * The device transport type.
      */
-    private final String UID;
+    private final String transportType;
 
     /**
-     * The device transport type.
+     * The device UID (unique identifier).
      */
-    private final String transportType;
+    private final String uid;
 
     /**
      * Constructs a CaptureDeviceInfo object with the specified name, media
@@ -37,14 +37,14 @@ public class ExtendedCaptureDeviceInfo
      */
     public ExtendedCaptureDeviceInfo(
             CaptureDeviceInfo captureDeviceInfo,
-            String UID,
+            String uid,
             String transportType)
     {
         this(
                 captureDeviceInfo.getName(),
                 captureDeviceInfo.getLocator(),
                 captureDeviceInfo.getFormats(),
-                UID,
+                uid,
                 transportType);
     }
 
@@ -59,82 +59,92 @@ public ExtendedCaptureDeviceInfo(
      * @param transportType The device transport type.
      */
     public ExtendedCaptureDeviceInfo(
-            String name,
-            MediaLocator locator,
-            Format[] formats,
-            String UID,
-            String transportType)
+            String name, MediaLocator locator, Format[] formats,
+            String uid, String transportType)
     {
         super(name, locator, formats);
 
-        this.UID = UID;
+        this.uid = uid;
         this.transportType = transportType;
     }
 
     /**
-     * Returns the device UID (unique identifier).
+     * Determines whether a specific <tt>Object</tt> is equal (by value) to this
+     * instance.
      *
-     * @return The device UID (unique identifier).
+     * @param obj the <tt>Object</tt> to be determined whether it is equal (by
+     * value) to this instance
+     * @return <tt>true</tt> if the specified <tt>obj</tt> is equal (by value)
+     * to this instance; otherwise, <tt>false</tt>
      */
-    public String getUID()
+    @Override
+    public boolean equals(Object obj)
     {
-        return this.UID;
+        return
+            (obj != null)
+                && (obj instanceof ExtendedCaptureDeviceInfo)
+                && getIdentifier().equals(
+                        ((ExtendedCaptureDeviceInfo) obj).getIdentifier());
     }
 
     /**
-     * Returns the device transport type.
+     * Returns the device identifier used to save and load device preferences.
+     * It is composed by the system UID if not null. Otherwise returns the
+     * device name and (if not null) the transport type.
      *
-     * @return The device transport type.
+     * @return The device identifier.
      */
-    public String getTransportType()
+    public String getIdentifier()
     {
-        return this.transportType;
+        return (uid == null) ? name : uid;
     }
 
     /**
-     * Returns if the transport type matches the one given in parameter.
-     *
-     * The transport type to compare with.
+     * Returns the device transport type of this instance.
      *
-     * @return True if the transport type matches the one given in parameter.
-     * False otherwise.
+     * @return the device transport type of this instance
      */
-    public boolean isSameTransportType(String transportType)
+    public String getTransportType()
     {
-        if(this.transportType == null)
-        {
-            return (transportType == null);
-        }
-        return this.transportType.equals(transportType);
+        return transportType;
     }
 
-    @Override
-    public boolean equals(Object obj)
+    /**
+     * Returns the device UID (unique identifier) of this instance.
+     *
+     * @return the device UID (unique identifier) of this instance
+     */
+    public String getUID()
     {
-        if(obj != null
-                && obj instanceof ExtendedCaptureDeviceInfo)
-        {
-            return this.getIdentifier().equals(
-                    ((ExtendedCaptureDeviceInfo) obj).getIdentifier());
-        }
-        return false;
+        return uid;
     }
 
+    /**
+     * Returns a hash code value for this object for the benefit of hashtables.
+     *
+     * @return a hash code value for this object for the benefit of hashtables
+     */
     @Override
     public int hashCode()
     {
-        return this.getIdentifier().hashCode();
+        return getIdentifier().hashCode();
     }
 
     /**
-     * Returns the device identifier used to save and load device preferences.
-     * It is composed by the system UID if not null. Otherwise returns the
-     * device name and (if not null) the transport type.
+     * Determines whether a specific transport type is equal to/the same as the
+     * transport type of this instance.
      *
-     * @return The device identifier.
+     * @param transportType the transport type to compare to the transport type
+     * of this instance
+     * @return <tt>true</tt> if the specified <tt>transportType</tt> is equal
+     * to/the same as the transport type of this instance; otherwise,
+     * <tt>false</tt>
      */
-    public String getIdentifier()
+    public boolean isSameTransportType(String transportType)
     {
-        return (UID == null) ? name : UID;
+        return
+            (this.transportType == null)
+                ? (transportType == null)
+                : this.transportType.equals(transportType);
     }
 }
diff --git a/src/org/jitsi/impl/neomedia/device/PlaybackDevices.java b/src/org/jitsi/impl/neomedia/device/PlaybackDevices.java
index 8f2715fc837750c442d089675c78a594e642b17b..e7b64895035befc2c6ce63950330a89dc2c19d65 100644
--- a/src/org/jitsi/impl/neomedia/device/PlaybackDevices.java
+++ b/src/org/jitsi/impl/neomedia/device/PlaybackDevices.java
@@ -45,31 +45,31 @@ public PlaybackDevices(AudioSystem audioSystem)
      */
     public List<ExtendedCaptureDeviceInfo> getDevices()
     {
-        return (this.activePlaybackDevices == null)
+        return (activePlaybackDevices == null)
                 ? null
                 : new ArrayList<ExtendedCaptureDeviceInfo>(
-                        this.activePlaybackDevices);
+                        activePlaybackDevices);
     }
 
     /**
-     * Sets the list of the active devices.
+     * Returns the property of the capture devices.
      *
-     * @param activeDevices The list of the active devices.
+     * @return The property of the capture devices.
      */
-    public void setActiveDevices(List<ExtendedCaptureDeviceInfo> activeDevices)
+    protected String getPropDevice()
     {
-        this.activePlaybackDevices = (activeDevices == null)
-                ? null
-                : new ArrayList<ExtendedCaptureDeviceInfo>(activeDevices);
+        return PROP_DEVICE;
     }
 
     /**
-     * Returns the property of the capture devices.
+     * Sets the list of the active devices.
      *
-     * @return The property of the capture devices.
+     * @param activeDevices The list of the active devices.
      */
-    protected String getPropDevice()
+    public void setActiveDevices(List<ExtendedCaptureDeviceInfo> activeDevices)
     {
-        return PROP_DEVICE;
+        activePlaybackDevices = (activeDevices == null)
+                ? null
+                : new ArrayList<ExtendedCaptureDeviceInfo>(activeDevices);
     }
 }
diff --git a/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java b/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java
index 41fad820066ff951977841b9a3f847550539a977..2af313dd1526ab37dddc1a1dea6670525adc3bee 100644
--- a/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java
+++ b/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java
@@ -8,6 +8,7 @@
 
 import java.lang.ref.*;
 import java.util.*;
+import java.util.regex.*;
 
 import javax.media.*;
 import javax.media.format.*;
@@ -220,10 +221,13 @@ protected void doInitialize()
         long sampleFormat = Pa.getPaSampleFormat(sampleSizeInBits);
         int defaultInputDeviceIndex = Pa.GetDefaultInputDevice();
         int defaultOutputDeviceIndex = Pa.GetDefaultOutputDevice();
+        List<ExtendedCaptureDeviceInfo> captureAndPlaybackDevices
+            = new LinkedList<ExtendedCaptureDeviceInfo>();
         List<ExtendedCaptureDeviceInfo> captureDevices
             = new LinkedList<ExtendedCaptureDeviceInfo>();
         List<ExtendedCaptureDeviceInfo> playbackDevices
             = new LinkedList<ExtendedCaptureDeviceInfo>();
+        final boolean loggerIsDebugEnabled = logger.isDebugEnabled();
 
         for (int deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
         {
@@ -242,83 +246,152 @@ protected void doInitialize()
             String deviceUID
                 = Pa.DeviceInfo_getDeviceUID(deviceInfo);
 
+            /*
+             * TODO The intention of reinitialize() was to perform the
+             * initialization from scratch. However, AudioSystem was later
+             * changed to disobey. But we should at least search through both
+             * CAPTURE_INDEX and PLAYBACK_INDEX.
+             */
+            List<ExtendedCaptureDeviceInfo> existingCdis
+                = getDevices(CAPTURE_INDEX);
             ExtendedCaptureDeviceInfo cdi = null;
-            List<ExtendedCaptureDeviceInfo> devices = getDevices(CAPTURE_INDEX);
-            boolean found = false;
-            // Search if the device is already initiated. If yes used it,
-            // otherwise a call currently using this device will fail.
-            for(int i = 0; devices !=null && i < devices.size() && !found; ++i)
+
+            if (existingCdis != null)
             {
-                // using identifier (name or uid, cause there can be some
-                // uid that are null)
-                String id = devices.get(i).getIdentifier();
-                if(id.equals(deviceUID) || id.equals(name))
+                for (ExtendedCaptureDeviceInfo existingCdi : existingCdis)
                 {
-                    cdi = devices.get(i);
-                    found = true;
+                    /*
+                     * The deviceUID is optional so a device may be identified
+                     * by deviceUID if it is available or by name if the
+                     * deviceUID is not available.
+                     */
+                    String id = existingCdi.getIdentifier();
+
+                    if (id.equals(deviceUID) || id.equals(name))
+                    {
+                        cdi = existingCdi;
+                        break;
+                    }
                 }
             }
-            // If not found, then we must initialized this new device.
-            if(!found)
+            if (cdi == null)
             {
-                cdi = new ExtendedCaptureDeviceInfo(
-                    name,
-                    new MediaLocator(LOCATOR_PROTOCOL + ":#" + deviceIndex),
-                    new Format[]
-                    {
-                        new AudioFormat(
-                                AudioFormat.LINEAR,
-                                (maxInputChannels > 0)
-                                    ? getSupportedSampleRate(
-                                            true,
-                                            deviceIndex,
-                                            channels,
-                                            sampleFormat)
-                                    : Pa.DEFAULT_SAMPLE_RATE,
-                                sampleSizeInBits,
-                                channels,
-                                AudioFormat.LITTLE_ENDIAN,
-                                AudioFormat.SIGNED,
-                                Format.NOT_SPECIFIED /* frameSizeInBits */,
-                                Format.NOT_SPECIFIED /* frameRate */,
-                                Format.byteArray)
-                    },
-                    deviceUID,
-                    transportType);
+                cdi
+                    = new ExtendedCaptureDeviceInfo(
+                            name,
+                            new MediaLocator(
+                                    LOCATOR_PROTOCOL + ":#" + deviceIndex),
+                            new Format[]
+                            {
+                                new AudioFormat(
+                                        AudioFormat.LINEAR,
+                                        (maxInputChannels > 0)
+                                            ? getSupportedSampleRate(
+                                                    true,
+                                                    deviceIndex,
+                                                    channels,
+                                                    sampleFormat)
+                                            : Pa.DEFAULT_SAMPLE_RATE,
+                                        sampleSizeInBits,
+                                        channels,
+                                        AudioFormat.LITTLE_ENDIAN,
+                                        AudioFormat.SIGNED,
+                                        Format.NOT_SPECIFIED /* frameSizeInBits */,
+                                        Format.NOT_SPECIFIED /* frameRate */,
+                                        Format.byteArray)
+                            },
+                            deviceUID,
+                            transportType);
             }
 
+            /*
+             * When we perform automatic selection of capture and
+             * playback/notify devices, we would like to pick up devices from
+             * one and the same hardware because that sound like a natural
+             * expectation from the point of view of the user. In order to
+             * achieve that, we will bring the devices which support both
+             * capture and playback to the top.
+             */
             if (maxInputChannels > 0)
             {
-                if (deviceIndex == defaultInputDeviceIndex)
+                List<ExtendedCaptureDeviceInfo> devices;
+
+                if (maxOutputChannels > 0)
+                    devices = captureAndPlaybackDevices;
+                else
+                    devices = captureDevices;
+
+                if ((deviceIndex == defaultInputDeviceIndex)
+                        || ((maxOutputChannels > 0)
+                                && (deviceIndex == defaultOutputDeviceIndex)))
                 {
-                    captureDevices.add(0, cdi);
-                    if (logger.isDebugEnabled())
+                    devices.add(0, cdi);
+                    if (loggerIsDebugEnabled)
                         logger.debug("Added default capture device: " + name);
                 }
                 else
                 {
-                    captureDevices.add(cdi);
-                    if (logger.isDebugEnabled())
+                    devices.add(cdi);
+                    if (loggerIsDebugEnabled)
                         logger.debug("Added capture device: " + name);
                 }
+                if (loggerIsDebugEnabled && (maxInputChannels > 0))
+                {
+                    if (deviceIndex == defaultOutputDeviceIndex)
+                        logger.debug("Added default playback device: " + name);
+                    else
+                        logger.debug("Added playback device: " + name);
+                }
             }
-            if (maxOutputChannels > 0)
+            else if (maxOutputChannels > 0)
             {
                 if (deviceIndex == defaultOutputDeviceIndex)
                 {
                     playbackDevices.add(0, cdi);
-                    if (logger.isDebugEnabled())
+                    if (loggerIsDebugEnabled)
                         logger.debug("Added default playback device: " + name);
                 }
                 else
                 {
                     playbackDevices.add(cdi);
-                    if (logger.isDebugEnabled())
+                    if (loggerIsDebugEnabled)
                         logger.debug("Added playback device: " + name);
                 }
             }
         }
 
+        /*
+         * Make sure that devices which support both capture and playback are
+         * reported as such and are preferred over devices which support either
+         * capture or playback (in order to achieve our goal to have automatic
+         * selection pick up devices from one and the same hardware).
+         */
+        if (!captureDevices.isEmpty() && !playbackDevices.isEmpty())
+        {
+            /*
+             * Event if we have not been provided with the information regarding
+             * the matching of the capture and playback/notify devices from one
+             * and the same hardware, we may still be able to deduce it by
+             * examining their names.
+             */
+            matchDevicesByName(captureDevices, playbackDevices);
+        }
+        /*
+         * Of course, of highest reliability is the fact that a specific
+         * instance supports both capture and playback.
+         */
+        if (!captureAndPlaybackDevices.isEmpty())
+        {
+            for (int i = captureAndPlaybackDevices.size() - 1; i >= 0; i--)
+            {
+                ExtendedCaptureDeviceInfo cdi
+                    = captureAndPlaybackDevices.get(i);
+
+                captureDevices.add(0, cdi);
+                playbackDevices.add(0, cdi);
+            }
+        }
+
         setCaptureDevices(captureDevices);
         setPlaybackDevices(playbackDevices);
 
@@ -488,6 +561,87 @@ private static double getSupportedSampleRate(
         return supportedSampleRate;
     }
 
+    /**
+     * Attempts to reorder specific lists of capture and playback/notify
+     * <tt>ExtendedCaptureDeviceInfo</tt>s so that devices from the same
+     * hardware appear at the same indices in the respective lists. The judgment
+     * with respect to the belonging to the same hardware is based on the names
+     * of the specified <tt>ExtendedCaptureDeviceInfo</tt>s. The implementation
+     * is provided as a fallback to stand in for scenarios in which more
+     * accurate relevant information is not available.
+     *
+     * @param captureDevices
+     * @param playbackDevices
+     */
+    private void matchDevicesByName(
+            List<ExtendedCaptureDeviceInfo> captureDevices,
+            List<ExtendedCaptureDeviceInfo> playbackDevices)
+    {
+        Iterator<ExtendedCaptureDeviceInfo> captureIter
+            = captureDevices.iterator();
+        Pattern pattern
+            = Pattern.compile(
+                    "microphone|speakers|\\p{Space}|\\(|\\)",
+                    Pattern.CASE_INSENSITIVE);
+        LinkedList<ExtendedCaptureDeviceInfo> captureDevicesWithPlayback
+            = new LinkedList<ExtendedCaptureDeviceInfo>();
+        LinkedList<ExtendedCaptureDeviceInfo> playbackDevicesWithCapture
+            = new LinkedList<ExtendedCaptureDeviceInfo>();
+        int count = 0;
+
+        while (captureIter.hasNext())
+        {
+            ExtendedCaptureDeviceInfo captureDevice = captureIter.next();
+            String captureName = captureDevice.getName();
+
+            if (captureName != null)
+            {
+                captureName = pattern.matcher(captureName).replaceAll("");
+                if (captureName.length() != 0)
+                {
+                    Iterator<ExtendedCaptureDeviceInfo> playbackIter
+                        = playbackDevices.iterator();
+                    ExtendedCaptureDeviceInfo matchingPlaybackDevice = null;
+
+                    while (playbackIter.hasNext())
+                    {
+                        ExtendedCaptureDeviceInfo playbackDevice
+                            = playbackIter.next();
+                        String playbackName = playbackDevice.getName();
+
+                        if (playbackName != null)
+                        {
+                            playbackName
+                                = pattern
+                                    .matcher(playbackName)
+                                        .replaceAll("");
+                            if (captureName.equals(playbackName))
+                            {
+                                playbackIter.remove();
+                                matchingPlaybackDevice = playbackDevice;
+                                break;
+                            }
+                        }
+                    }
+                    if (matchingPlaybackDevice != null)
+                    {
+                        captureIter.remove();
+                        captureDevicesWithPlayback.add(captureDevice);
+                        playbackDevicesWithCapture.add(
+                                matchingPlaybackDevice);
+                        count++;
+                    }
+                }
+            }
+        }
+
+        for (int i = count - 1; i >= 0; i--)
+        {
+            captureDevices.add(0, captureDevicesWithPlayback.get(i));
+            playbackDevices.add(0, playbackDevicesWithCapture.get(i));
+        }
+    }
+
     /**
      * Reinitializes this <tt>PortAudioSystem</tt> in order to bring it up to
      * date with possible changes in the PortAudio devices. Invokes
diff --git a/src/org/jitsi/impl/neomedia/maccoreaudio/CoreAudioVolumeControl.java b/src/org/jitsi/impl/neomedia/maccoreaudio/CoreAudioVolumeControl.java
index 217906ba482b31624174b9b074375eade16a3b2d..873653501d3deda9e3556f0cf63e8a5acb4d592f 100644
--- a/src/org/jitsi/impl/neomedia/maccoreaudio/CoreAudioVolumeControl.java
+++ b/src/org/jitsi/impl/neomedia/maccoreaudio/CoreAudioVolumeControl.java
@@ -7,7 +7,6 @@
 package org.jitsi.impl.neomedia.maccoreaudio;
 
 import org.jitsi.impl.neomedia.*;
-import org.jitsi.impl.neomedia.device.*;
 import org.jitsi.util.*;
 
 /**
@@ -56,7 +55,7 @@ protected int setInputDeviceVolume(String deviceUID, float volume)
         if(CoreAudioDevice.setInputDeviceVolume(deviceUID, volume) != 0)
         {
             logger.debug(
-                    "Could not change MacOsX CoreAudio input device level");
+                    "Could not change Mac OS X CoreAudio input device level");
             return -1;
         }
         return 0;
@@ -68,18 +67,14 @@ protected int setInputDeviceVolume(String deviceUID, float volume)
      * @param deviceUID The device ID.
      *
      * @Return A scalar value between 0 and 1 if everything works fine. -1 if an
-     * error occured.
+     * error occurred.
      */
     protected float getInputDeviceVolume(String deviceUID)
     {
-        float volume;
+        float volume = CoreAudioDevice.getInputDeviceVolume(deviceUID);
 
-        if((volume = CoreAudioDevice.getInputDeviceVolume(deviceUID))
-                != 0)
-        {
-            logger.debug(
-                    "Could not get MacOsX CoreAudio input device level");
-        }
+        if(logger.isDebugEnabled() && (volume != 0))
+            logger.debug("Could not get Mac OS X CoreAudio input device level");
 
         return volume;
     }
diff --git a/src/org/jitsi/impl/neomedia/notify/AudioNotifierServiceImpl.java b/src/org/jitsi/impl/neomedia/notify/AudioNotifierServiceImpl.java
index 574716fbd4b4d33c2496fef721ce2dcab8e61e3f..8e7b81507ef333854623c1e569ca661520717746 100644
--- a/src/org/jitsi/impl/neomedia/notify/AudioNotifierServiceImpl.java
+++ b/src/org/jitsi/impl/neomedia/notify/AudioNotifierServiceImpl.java
@@ -7,7 +7,6 @@
 package org.jitsi.impl.neomedia.notify;
 
 import java.beans.*;
-import java.net.*;
 import java.util.*;
 import java.util.concurrent.*;
 
@@ -16,8 +15,6 @@
 import org.jitsi.impl.neomedia.*;
 import org.jitsi.impl.neomedia.device.*;
 import org.jitsi.service.audionotifier.*;
-import org.jitsi.service.libjitsi.*;
-import org.jitsi.service.resources.*;
 
 /**
  * The implementation of <tt>AudioNotifierService</tt>.
diff --git a/src/org/jitsi/impl/neomedia/portaudio/Pa.java b/src/org/jitsi/impl/neomedia/portaudio/Pa.java
index 49babcdc0ecb0c6bfd4edf817bb332f1e81c3301..072740c77ad319340ecf25e0f8da6a83ddaaf3df 100644
--- a/src/org/jitsi/impl/neomedia/portaudio/Pa.java
+++ b/src/org/jitsi/impl/neomedia/portaudio/Pa.java
@@ -6,7 +6,6 @@
  */
 package org.jitsi.impl.neomedia.portaudio;
 
-import java.io.*;
 import java.lang.reflect.*;
 
 import org.jitsi.service.configuration.*;
diff --git a/src/org/jitsi/impl/neomedia/transform/pt/PayloadTypeTransformEngine.java b/src/org/jitsi/impl/neomedia/transform/pt/PayloadTypeTransformEngine.java
index d05427f2401eedc0f8c691339e7d850892dc339c..d2db8e64dfbd8834dae65ca41878ec57ff665833 100644
--- a/src/org/jitsi/impl/neomedia/transform/pt/PayloadTypeTransformEngine.java
+++ b/src/org/jitsi/impl/neomedia/transform/pt/PayloadTypeTransformEngine.java
@@ -34,7 +34,7 @@ public class PayloadTypeTransformEngine
     private Map<Byte, Byte> mappingOverrides = new HashMap<Byte, Byte>();
 
     /**
-     * This map is a copy of <tt>mappingOverride</tt> that we use durig actual
+     * This map is a copy of <tt>mappingOverride</tt> that we use during actual
      * transformation
      */
     private Map<Byte, Byte> mappingOverridesCopy = null;
@@ -118,19 +118,16 @@ public PacketTransformer getRTCPTransformer()
      * thread-safe way without using synchronization.
      *
      * @param originalPt the payload type that we are overriding
-     * @param overloadPt the payload type that we are overriging it with
+     * @param overridePt the payload type that we are overriding it with
      */
-
-    public void addPTMappingOverride(byte originalPt, byte overloadPt)
+    public void addPTMappingOverride(byte originalPt, byte overridePt)
     {
-        if (mappingOverrides.containsKey(originalPt)
-            && mappingOverrides.get(originalPt) == overloadPt)
+        Byte existingOverride = mappingOverrides.get(originalPt);
+
+        if ((existingOverride == null) || (existingOverride != overridePt))
         {
-            return;
+            mappingOverrides.put(originalPt, overridePt);
+            mappingOverridesCopy = new HashMap<Byte, Byte>(mappingOverrides);
         }
-
-        mappingOverrides.put(originalPt, overloadPt);
-
-        mappingOverridesCopy = new HashMap(mappingOverrides);
     }
 }
diff --git a/src/org/jitsi/impl/neomedia/wincoreaudio/CoreAudioVolumeControl.java b/src/org/jitsi/impl/neomedia/wincoreaudio/CoreAudioVolumeControl.java
index 188540b445d344c46ad166473531ad3be58b745c..e6052abdacb61c2dd3cae6082db351d74756b2a4 100644
--- a/src/org/jitsi/impl/neomedia/wincoreaudio/CoreAudioVolumeControl.java
+++ b/src/org/jitsi/impl/neomedia/wincoreaudio/CoreAudioVolumeControl.java
@@ -7,7 +7,6 @@
 package org.jitsi.impl.neomedia.wincoreaudio;
 
 import org.jitsi.impl.neomedia.*;
-import org.jitsi.impl.neomedia.device.*;
 import org.jitsi.util.*;
 
 /**
@@ -78,7 +77,7 @@ protected int setInputDeviceVolume(String deviceUID, float volume)
      * @param deviceUID The device ID.
      *
      * @Return A scalar value between 0 and 1 if everything works fine. -1 if an
-     * error occured.
+     * error occurred.
      */
     protected float getInputDeviceVolume(String deviceUID)
     {
diff --git a/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java b/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java
index 5d484612f621675e119eb35b34fe979bb507ae72..f42fa6b93667d47888f922999fb4975e731e0e0a 100644
--- a/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java
+++ b/src/org/jitsi/service/audionotifier/AbstractSCAudioClip.java
@@ -6,7 +6,6 @@
  */
 package org.jitsi.service.audionotifier;
 
-import java.net.*;
 import java.util.concurrent.*;
 
 /**