diff --git a/lib/native/windows-64/jnwincoreaudio.dll b/lib/native/windows-64/jnwincoreaudio.dll
index 2b0bac5c104f9894577c899445f278dbbcbcd7ce..6ded173cda25bc7c162b9ed4e9a55f7719c94cd0 100644
Binary files a/lib/native/windows-64/jnwincoreaudio.dll and b/lib/native/windows-64/jnwincoreaudio.dll differ
diff --git a/lib/native/windows/jnwincoreaudio.dll b/lib/native/windows/jnwincoreaudio.dll
index 9f1768b7f65952c06ff79882bce8525e5083cea3..cbc7a20c6ee184e2d022b518df7f39569e42ad82 100644
Binary files a/lib/native/windows/jnwincoreaudio.dll and b/lib/native/windows/jnwincoreaudio.dll differ
diff --git a/src/native/windows/coreaudio/jni/org_jitsi_impl_neomedia_CoreAudioDevice.c b/src/native/windows/coreaudio/jni/org_jitsi_impl_neomedia_CoreAudioDevice.c
index 2afc9305c4cd1c46752ca1afcb5edf5cba0f052d..68d3704ff626bd36bea4e5c2503efb22c1554e0f 100644
--- a/src/native/windows/coreaudio/jni/org_jitsi_impl_neomedia_CoreAudioDevice.c
+++ b/src/native/windows/coreaudio/jni/org_jitsi_impl_neomedia_CoreAudioDevice.c
@@ -49,6 +49,21 @@ Java_org_jitsi_impl_neomedia_CoreAudioDevice_getDeviceNameBytes
     return deviceNameBytes;
 }
 
+JNIEXPORT jbyteArray JNICALL
+Java_org_jitsi_impl_neomedia_CoreAudioDevice_getDeviceModelIdentifierBytes
+  (JNIEnv *env, jclass clazz, jstring deviceUID)
+{
+    const char * deviceUIDPtr = env->GetStringUTFChars(deviceUID, 0);
+    char * deviceModelIdentifier = getDeviceModelIdentifier(deviceUIDPtr);
+    jbyteArray deviceModelIdentifierBytes
+        = getStrBytes(env, deviceModelIdentifier);
+    // Free
+    free(deviceModelIdentifier);
+    env->ReleaseStringUTFChars(deviceUID, deviceUIDPtr);
+
+    return deviceModelIdentifierBytes;
+}
+
 JNIEXPORT jint JNICALL
 Java_org_jitsi_impl_neomedia_CoreAudioDevice_setInputDeviceVolume
   (JNIEnv *env, jclass clazz, jstring deviceUID, jfloat volume)
diff --git a/src/native/windows/coreaudio/lib/device.c b/src/native/windows/coreaudio/lib/device.c
index 5895b46f93bfb9b1b4eda6413922db00bd31fb23..ebeb979f5ce5909da03af58ccf2052a26ad33ff3 100644
--- a/src/native/windows/coreaudio/lib/device.c
+++ b/src/native/windows/coreaudio/lib/device.c
@@ -16,6 +16,7 @@
 #include <commctrl.h> // Must be defined after mmdeviceapi.h
 #include <endpointvolume.h> // Must be defined after mmdeviceapi.h
 
+
 /**
  * Functions to list, access and modifies audio devices via coreaudio.
  *
@@ -31,6 +32,16 @@ IAudioEndpointVolume * getEndpointVolume(
 void freeEndpointVolume(
         IAudioEndpointVolume * endpointVolume);
 
+char* getDeviceDescription(
+        const char * deviceUID);
+
+char* getDeviceInterfaceName(
+        const char * deviceUID);
+
+char* getDeviceProperty(
+        const char * deviceUID,
+        PROPERTYKEY propertyKey);
+
 int setDeviceVolume(
         const char * deviceUID,
         float volume);
@@ -38,8 +49,15 @@ int setDeviceVolume(
 float getDeviceVolume(
         const char * deviceUID);
 
+// Definitions find in "functiondiscoverykeys_devpkey.h" but not found by
+// MINGW64 TDM-gcc compiler.
+DEFINE_PROPERTYKEY(PKEY_DeviceInterface_FriendlyName,  0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 2); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_DeviceDesc,             0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 2);     // DEVPROP_TYPE_STRING
 DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName,           0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);    // DEVPROP_TYPE_STRING
 
+
+DEFINE_PROPERTYKEY(PKEY_Device_BusNumber,              0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 23);    // DEVPROP_TYPE_UINT32
+
 /**
  * Initializes the COM component. This function must be called first in order to
  * able each following function to work correctly. Once finished, the caller of
@@ -224,7 +242,8 @@ void freeEndpointVolume(
 
 /**
  * Returns the device name for the given device. Or NULL, if not available. The
- * returned string must be freed by the caller.
+ * returned string must be freed by the caller. The device name is composed of
+ * the device description and of the device interface name.
  *
  * @param device The device to get the name from.
  *
@@ -234,10 +253,162 @@ void freeEndpointVolume(
 char* getDeviceName(
         const char * deviceUID)
 {
-    size_t deviceNameLength;
-    char * deviceName = NULL;
-    PROPVARIANT propertyDeviceName;
-    PropVariantInit(&propertyDeviceName);
+    return getDeviceProperty(deviceUID, PKEY_Device_FriendlyName);
+}
+
+/**
+ * Returns the device model identifier for the given device. Or NULL, if not
+ * available. The returned string must be freed by the caller.
+ *
+ * @param device The device to get the name from.
+ *
+ * @return The device model identifier for the given device. Or NULL, if not
+ * available. The returned string must be freed by the caller.
+ */
+char* getDeviceModelIdentifier(
+        const char * deviceUID)
+{
+    int deviceModelIdentifierLength;
+    char * deviceModelIdentifier = NULL;
+    char * deviceDescription;
+    char * deviceInterface;
+    char * genericDeviceInterface;
+
+    if((deviceDescription = getDeviceDescription(deviceUID)) == NULL)
+    {
+        fprintf(stderr,
+                "getDeviceModelIdentifier (coreaudio/device.c): \
+                    \n\tgetDeviceDescription\n");
+        fflush(stderr);
+        return NULL;
+    }
+    if((deviceInterface = getDeviceInterfaceName(deviceUID)) == NULL)
+    {
+        fprintf(stderr,
+                "getDeviceModelIdentifier (coreaudio/device.c): \
+                    \n\tgetDeviceInterfaceName\n");
+        fflush(stderr);
+        return NULL;
+    }
+
+    // A USB device (without a serial ID) puts into a USB port will add the
+    // port number (if greater than 1) with the following prefix: "X- "
+    // (with X the port number).
+    genericDeviceInterface = deviceInterface;
+    // First skip the number at the beginning of the prefix.
+    while(genericDeviceInterface[0] != '\0'
+            && genericDeviceInterface[0] >= '0'
+            && genericDeviceInterface[0] <= '9')
+    {
+        ++genericDeviceInterface;
+    }
+    // Then skips the "-".
+    if(genericDeviceInterface[0] != '\0'
+            && genericDeviceInterface[0] == '-')
+    {
+        ++genericDeviceInterface;
+    }
+    // Finally skips the " ".
+    if(genericDeviceInterface[0] != '\0'
+            && genericDeviceInterface[0] == ' ')
+    {
+        ++genericDeviceInterface;
+    }
+    // If we have reached the end of the string, then the string does not
+    // contain the prefix.
+    if(genericDeviceInterface[0] == '\0')
+    {
+        genericDeviceInterface = deviceInterface;
+    }
+
+    // Finally, concatenate the device description and its generic device
+    // interface.
+    deviceModelIdentifierLength
+        = strlen(deviceDescription) + 2 + strlen(genericDeviceInterface) + 2;
+    if((deviceModelIdentifier
+                = (char*) malloc(deviceModelIdentifierLength * sizeof(char)))
+            == NULL)
+    {
+        fprintf(stderr,
+                "getDeviceModelIdentifier (coreaudio/device.c): \
+                    \n\tmalloc\n");
+        fflush(stderr);
+        return NULL;
+    }
+    if(snprintf(
+            deviceModelIdentifier,
+            deviceModelIdentifierLength,
+            "%s (%s)",
+            deviceDescription,
+            genericDeviceInterface) != (deviceModelIdentifierLength - 1))
+    {
+        free(deviceModelIdentifier);
+        fprintf(stderr,
+                "getDeviceModelIdentifier (coreaudio/device.c): \
+                    \n\tsnprintf\n");
+        fflush(stderr);
+        return NULL;
+    }
+
+    // Frees memory.
+    free(deviceDescription);
+    free(deviceInterface);
+
+    return deviceModelIdentifier;
+}
+
+/**
+ * Returns the device description for the given device. Or NULL, if not
+ * available. The returned string must be freed by the caller. The device
+ * description is a generic name such as "microphone", "speaker", etc.
+ *
+ * @param device The device to get the name from.
+ *
+ * @return The device description for the given device. Or NULL, if not
+ * available. The returned string must be freed by the caller.
+ */
+char* getDeviceDescription(
+        const char * deviceUID)
+{
+    return getDeviceProperty(deviceUID, PKEY_Device_DeviceDesc);
+}
+
+/**
+ * Returns the device interface name for the given device. Or NULL, if not
+ * available. The returned string must be freed by the caller. The device
+ * interface name describes the way the device is connected, such as "USB audio
+ * adapter".
+ *
+ * @param device The device to get the name from.
+ *
+ * @return The device interface name for the given device. Or NULL, if not
+ * available. The returned string must be freed by the caller.
+ */
+char* getDeviceInterfaceName(
+        const char * deviceUID)
+{
+    return getDeviceProperty(deviceUID, PKEY_DeviceInterface_FriendlyName);
+}
+
+/**
+ * Returns the device property for the given device. Or NULL, if not available.
+ * The returned string must be freed by the caller.
+ *
+ * @param device The device to get the name from.
+ * @param propertyKey The requested property (i.e. PKEY_Device_FriendlyName for
+ * the device name).
+ *
+ * @return The device property for the given device. Or NULL, if not available.
+ * The returned string must be freed by the caller.
+ */
+char* getDeviceProperty(
+        const char * deviceUID,
+        PROPERTYKEY propertyKey)
+{
+    size_t devicePropertyLength;
+    char * deviceProperty = NULL;
+    PROPVARIANT propertyDevice;
+    PropVariantInit(&propertyDevice);
     IPropertyStore * properties = NULL;
 
     // Gets the audio device.
@@ -245,7 +416,7 @@ char* getDeviceName(
     if(device == NULL)
     {
         fprintf(stderr,
-                "getDeviceName (coreaudio/device.c): \
+                "getDeviceProperty (coreaudio/device.c): \
                     \n\tgetDevice\n");
         fflush(stderr);
         return NULL;
@@ -255,35 +426,39 @@ char* getDeviceName(
     if(device->OpenPropertyStore(STGM_READ, &properties) != S_OK)
     {
         fprintf(stderr,
-                "getDeviceName (coreaudio/device.c): \
+                "getDeviceProperty (coreaudio/device.c): \
                     \n\tIMMDevice.OpenPropertyStore\n");
         fflush(stderr);
         return NULL;
     }
-    if(properties->GetValue(PKEY_Device_FriendlyName, &propertyDeviceName)
+    if(properties->GetValue(propertyKey, &propertyDevice)
             != S_OK)
     {
         fprintf(stderr,
-                "getDeviceName (coreaudio/device.c): \
+                "getDeviceProperty (coreaudio/device.c): \
                     \n\tIPropertyStore.GetValue\n");
         fflush(stderr);
         return NULL;
     }
-    deviceNameLength = wcslen(propertyDeviceName.pwszVal);
-    if((deviceName = (char *) malloc((deviceNameLength + 1) * sizeof(char)))
+    devicePropertyLength = wcslen(propertyDevice.pwszVal);
+    if((deviceProperty
+                = (char *) malloc((devicePropertyLength + 1) * sizeof(char)))
             == NULL)
     {
         fprintf(stderr,
-                "getDeviceName (coreaudio/device.c): \
+                "getDeviceProperty (coreaudio/device.c): \
                     \n\tmalloc\n");
         fflush(stderr);
         return NULL;
     }
-    if(wcstombs(deviceName, propertyDeviceName.pwszVal, deviceNameLength + 1)
-            != deviceNameLength)
+    if(wcstombs(
+                deviceProperty,
+                propertyDevice.pwszVal,
+                devicePropertyLength + 1)
+            != devicePropertyLength)
     {
         fprintf(stderr,
-                "getDeviceName (coreaudio/device.c): \
+                "getDeviceProperty (coreaudio/device.c): \
                     \n\twcstombs\n");
         fflush(stderr);
         return NULL;
@@ -291,9 +466,9 @@ char* getDeviceName(
 
     // Frees.
     freeDevice(device);
-    PropVariantClear(&propertyDeviceName);
+    PropVariantClear(&propertyDevice);
 
-    return deviceName;
+    return deviceProperty;
 }
 
 /**
diff --git a/src/native/windows/coreaudio/lib/device.h b/src/native/windows/coreaudio/lib/device.h
index abc05f2eaa17e97304d094af81a41cab9c689787..0fc0417fd471e89f72aa2cd4cbf1335ce1fc8d19 100644
--- a/src/native/windows/coreaudio/lib/device.h
+++ b/src/native/windows/coreaudio/lib/device.h
@@ -28,6 +28,9 @@ void freeDevice(
 char* getDeviceName(
         const char * deviceUID);
 
+char* getDeviceModelIdentifier(
+        const char * deviceUID);
+
 int setInputDeviceVolume(
         const char * deviceUID,
         float volume);
diff --git a/src/org/jitsi/impl/neomedia/device/Devices.java b/src/org/jitsi/impl/neomedia/device/Devices.java
index 5bad919ced9c63afbc39ac9fbec6714e83c79556..c7e9ca320b8922bebc0e1d85f602a65eb5ee0213 100644
--- a/src/org/jitsi/impl/neomedia/device/Devices.java
+++ b/src/org/jitsi/impl/neomedia/device/Devices.java
@@ -73,7 +73,7 @@ public ExtendedCaptureDeviceInfo getDevice(
                 ExtendedCaptureDeviceInfo activeDevice = activeDevices.get(i);
 
                 if(!devicePreferences.contains(
-                            activeDevice.getModelIdentifier()))
+                            activeDevice.getIdentifier()))
                 {
                     // Adds the device in the preference list (to the end of the
                     // list, but the save device will push it to the top of
@@ -98,7 +98,7 @@ public ExtendedCaptureDeviceInfo getDevice(
                         // If we have found the "preferred" device among active
                         // device.
                         if(devicePreference.equals(
-                                activeDevice.getModelIdentifier()))
+                                activeDevice.getIdentifier()))
                         {
                             return activeDevice;
                         }
@@ -210,7 +210,7 @@ private void saveDevice(
         String selectedDeviceIdentifier
             = (device == null)
                 ? NoneAudioSystem.LOCATOR_PROTOCOL
-                : device.getModelIdentifier();
+                : device.getIdentifier();
 
         // Sorts the user preferences to put the selected device on top.
         addToDevicePreferences(
@@ -306,7 +306,7 @@ private void addToDevicePreferences(
                     for(ExtendedCaptureDeviceInfo activeDevice : activeDevices)
                     {
                         if(devicePreference.equals(
-                                    activeDevice.getModelIdentifier())
+                                    activeDevice.getIdentifier())
                                 || devicePreference.equals(
                                         NoneAudioSystem.LOCATOR_PROTOCOL))
                         {
@@ -337,7 +337,7 @@ private void renameOldFashionedIdentifier(
         for(ExtendedCaptureDeviceInfo activeDevice : activeDevices)
         {
             String name = activeDevice.getName();
-            String id = activeDevice.getModelIdentifier();
+            String id = activeDevice.getIdentifier();
 
             // We can only switch to the new fashioned notation, only if the OS
             // API gives us a unique identifier (different from the device
diff --git a/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java b/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java
index 43bb6a921d1c971735744b4a8f91ca0570bf8fc7..104bf1b118df3e0274eb6eabf6f37a0f1b584882 100644
--- a/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java
+++ b/src/org/jitsi/impl/neomedia/device/PortAudioSystem.java
@@ -264,6 +264,7 @@ protected void doInitialize()
             = new LinkedList<ExtendedCaptureDeviceInfo>();
         final boolean loggerIsDebugEnabled = logger.isDebugEnabled();
 
+        CoreAudioDevice.initDevices();
         for (int deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
         {
             long deviceInfo = Pa.GetDeviceInfo(deviceIndex);
@@ -397,6 +398,7 @@ else if (maxOutputChannels > 0)
                 }
             }
         }
+        CoreAudioDevice.freeDevices();
 
         /*
          * Make sure that devices which support both capture and playback are