Index: /pjproject/trunk/pjmedia/include/pjmedia-audiodev/audiodev.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia-audiodev/audiodev.h	(revision 3437)
+++ /pjproject/trunk/pjmedia/include/pjmedia-audiodev/audiodev.h	(revision 3438)
@@ -544,4 +544,18 @@
 PJ_DECL(pj_status_t)
 pjmedia_aud_unregister_factory(pjmedia_aud_dev_factory_create_func_ptr adf);
+
+
+/**
+ * Refresh the list of sound devices installed in the system. This function
+ * will only refresh the list of audio device so all active audio streams will
+ * be unaffected. After refreshing the device list, application MUST make sure
+ * to update all index references to audio devices (i.e. all variables of type
+ * pjmedia_aud_dev_index) before calling any function that accepts audio device
+ * index as its parameter.
+ *
+ * @return		PJ_SUCCESS on successful operation or the appropriate
+ *			error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_aud_dev_refresh(void);
 
 
Index: /pjproject/trunk/pjmedia/include/pjmedia-audiodev/audiodev_imp.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia-audiodev/audiodev_imp.h	(revision 3437)
+++ /pjproject/trunk/pjmedia/include/pjmedia-audiodev/audiodev_imp.h	(revision 3438)
@@ -93,4 +93,11 @@
 				 pjmedia_aud_stream **p_aud_strm);
 
+    /**
+     * Refresh the list of audio devices installed in the system.
+     *
+     * @param f		The audio device factory.
+     */
+    pj_status_t (*refresh)(pjmedia_aud_dev_factory *f);
+
 } pjmedia_aud_dev_factory_op;
 
Index: /pjproject/trunk/pjmedia/include/pjmedia/sound_port.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/sound_port.h	(revision 3437)
+++ /pjproject/trunk/pjmedia/include/pjmedia/sound_port.h	(revision 3438)
@@ -62,4 +62,31 @@
  
  */
+
+/**
+ * Sound port options.
+ */
+enum pjmedia_snd_port_option
+{
+    /** 
+     * Don't start the audio device when creating a sound port.
+     */    
+    PJMEDIA_SND_PORT_NO_AUTO_START = 1
+};
+
+/**
+ * This structure specifies the parameters to create the sound port.
+ */
+typedef struct pjmedia_snd_port_param
+{
+    /**
+     * Base structure.
+     */
+    pjmedia_aud_param base;
+    
+    /**
+     * Sound port creation options.
+     */
+    unsigned options;
+} pjmedia_snd_port_param;
 
 /**
@@ -87,5 +114,5 @@
  * @param bits_per_sample   Set the number of bits per sample. The normal 
  *			    value for this parameter is 16 bits per sample.
- * @param options	    Options flag, currently must be zero.
+ * @param options	    Options flag.
  * @param p_port	    Pointer to receive the sound device port instance.
  *
@@ -117,5 +144,5 @@
  * @param bits_per_sample   Set the number of bits per sample. The normal 
  *			    value for this parameter is 16 bits per sample.
- * @param options	    Options flag, currently must be zero.
+ * @param options	    Options flag.
  * @param p_port	    Pointer to receive the sound device port instance.
  *
@@ -146,5 +173,5 @@
  * @param bits_per_sample   Set the number of bits per sample. The normal 
  *			    value for this parameter is 16 bits per sample.
- * @param options	    Options flag, currently must be zero.
+ * @param options	    Options flag.
  * @param p_port	    Pointer to receive the sound device port instance.
  *
@@ -166,5 +193,5 @@
  *
  * @param pool		    Pool to allocate sound port structure.
- * @param prm		    Sound device settings.
+ * @param prm		    Sound port parameter.
  * @param p_port	    Pointer to receive the sound device port instance.
  *
@@ -173,5 +200,5 @@
  */
 PJ_DECL(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool,
-					      const pjmedia_aud_param *prm,
+					      const pjmedia_snd_port_param *prm,
 					      pjmedia_snd_port **p_port);
 
Index: /pjproject/trunk/pjmedia/src/pjmedia-audiodev/alsa_dev.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-audiodev/alsa_dev.c	(revision 3437)
+++ /pjproject/trunk/pjmedia/src/pjmedia-audiodev/alsa_dev.c	(revision 3438)
@@ -58,4 +58,5 @@
 static pj_status_t alsa_factory_init(pjmedia_aud_dev_factory *f);
 static pj_status_t alsa_factory_destroy(pjmedia_aud_dev_factory *f);
+static pj_status_t alsa_factory_refresh(pjmedia_aud_dev_factory *f);
 static unsigned    alsa_factory_get_dev_count(pjmedia_aud_dev_factory *f);
 static pj_status_t alsa_factory_get_dev_info(pjmedia_aud_dev_factory *f,
@@ -93,4 +94,5 @@
     pj_pool_factory		*pf;
     pj_pool_t			*pool;
+    pj_pool_t			*base_pool;
 
     unsigned			 dev_cnt;
@@ -134,5 +136,6 @@
     &alsa_factory_get_dev_info,
     &alsa_factory_default_param,
-    &alsa_factory_create_stream
+    &alsa_factory_create_stream,
+    &alsa_factory_refresh
 };
 
@@ -146,4 +149,18 @@
     &alsa_stream_destroy
 };
+
+static void null_alsa_error_handler (const char *file,
+				int line,
+				const char *function,
+				int err,
+				const char *fmt,
+				...)
+{
+    PJ_UNUSED_ARG(file);
+    PJ_UNUSED_ARG(line);
+    PJ_UNUSED_ARG(function);
+    PJ_UNUSED_ARG(err);
+    PJ_UNUSED_ARG(fmt);
+}
 
 static void alsa_error_handler (const char *file,
@@ -175,8 +192,7 @@
 
 
-static pj_status_t add_dev (struct alsa_factory *af, int card, int device)
+static pj_status_t add_dev (struct alsa_factory *af, const char *dev_name)
 {
     pjmedia_aud_dev_info *adi;
-    char dev_name[32];
     snd_pcm_t* pcm;
     int pb_result, ca_result;
@@ -187,6 +203,5 @@
     adi = &af->devs[af->dev_cnt];
 
-    TRACE_((THIS_FILE, "add_dev (%d, %d): Enter", card, device));
-    sprintf (dev_name, ALSA_DEVICE_NAME, card, device);
+    TRACE_((THIS_FILE, "add_dev (%s): Enter", dev_name));
 
     /* Try to open the device in playback mode */
@@ -246,8 +261,8 @@
     pj_pool_t *pool;
 
-    pool = pj_pool_create(pf, "alsa_aud", 256, 256, NULL);
+    pool = pj_pool_create(pf, "alsa_aud_base", 256, 256, NULL);
     af = PJ_POOL_ZALLOC_T(pool, struct alsa_factory);
     af->pf = pf;
-    af->pool = pool;
+    af->base_pool = pool;
     af->base.op = &alsa_factory_op;
 
@@ -259,13 +274,67 @@
 static pj_status_t alsa_factory_init(pjmedia_aud_dev_factory *f)
 {
+    pj_status_t status = alsa_factory_refresh(f);
+    if (PJ_SUCCESS != status)
+	return status;
+
+    PJ_LOG(4,(THIS_FILE, "ALSA initialized"));
+    return PJ_SUCCESS;
+}
+
+
+/* API: destroy factory */
+static pj_status_t alsa_factory_destroy(pjmedia_aud_dev_factory *f)
+{
     struct alsa_factory *af = (struct alsa_factory*)f;
-    int card, device;
+
+    if (af->pool)
+	pj_pool_release(af->pool);
+
+    if (af->base_pool) {
+	pj_pool_t *pool = af->base_pool;
+	af->base_pool = NULL;
+	pj_pool_release(pool);
+    }
+
+    /* Restore handler */
+    snd_lib_error_set_handler(NULL);
+
+    return PJ_SUCCESS;
+}
+
+
+/* API: refresh the device list */
+static pj_status_t alsa_factory_refresh(pjmedia_aud_dev_factory *f)
+{
+    struct alsa_factory *af = (struct alsa_factory*)f;
+    char **hints, **n;
+    int err;
 
     TRACE_((THIS_FILE, "pjmedia_snd_init: Enumerate sound devices"));
+
+    if (af->pool != NULL) {
+	pj_pool_release(af->pool);
+	af->pool = NULL;
+    }
+
+    af->pool = pj_pool_create(af->pf, "alsa_aud", 256, 256, NULL);
+    af->dev_cnt = 0;
+
     /* Enumerate sound devices */
-    for (card=0; card<MAX_SOUND_CARDS; card++) {
-	for (device=0; device<MAX_SOUND_DEVICES_PER_CARD; device++) {
-	    add_dev(af, card, device);
+    err = snd_device_name_hint(-1, "pcm", (void***)&hints);
+    if (err != 0)
+	return PJMEDIA_EAUD_SYSERR;
+
+    /* Set a null error handler prior to enumeration to suppress errors */
+    snd_lib_error_set_handler(null_alsa_error_handler);
+
+    n = hints;
+    while (*n != NULL) {
+	char *name = snd_device_name_get_hint(*n, "NAME");
+	if (name != NULL && 0 != strcmp("null", name)) {
+	    add_dev(af, name);
+	    free(name);
 	}
+	n++;
     }
 
@@ -273,24 +342,9 @@
      * error messages about invalid card/device ID.
      */
-    snd_lib_error_set_handler (alsa_error_handler);
+    snd_lib_error_set_handler(alsa_error_handler);
+
+    err = snd_device_name_free_hint((void**)hints);
 
     PJ_LOG(4,(THIS_FILE, "ALSA driver found %d devices", af->dev_cnt));
-    return PJ_SUCCESS;
-}
-
-
-/* API: destroy factory */
-static pj_status_t alsa_factory_destroy(pjmedia_aud_dev_factory *f)
-{
-    struct alsa_factory *af = (struct alsa_factory*)f;
-
-    if (af->pool) {
-	pj_pool_t *pool = af->pool;
-	af->pool = NULL;
-	pj_pool_release(pool);
-    }
-
-    /* Restore handler */
-    snd_lib_error_set_handler(NULL);
 
     return PJ_SUCCESS;
Index: /pjproject/trunk/pjmedia/src/pjmedia-audiodev/audiodev.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-audiodev/audiodev.c	(revision 3437)
+++ /pjproject/trunk/pjmedia/src/pjmedia-audiodev/audiodev.c	(revision 3438)
@@ -492,4 +492,23 @@
 }
 
+/* API: Refresh the list of sound devices installed in the system. */
+PJ_DEF(pj_status_t) pjmedia_aud_dev_refresh(void)
+{
+    unsigned i;
+    
+    for (i=0; i<aud_subsys.drv_cnt; ++i) {
+	struct driver *drv = &aud_subsys.drv[i];
+	
+	if (drv->f && drv->f->op->refresh) {
+	    pj_status_t status = drv->f->op->refresh(drv->f);
+	    if (status != PJ_SUCCESS) {
+		PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device "
+						 "list for %s", drv->name));
+	    }
+	}
+    }
+    return PJ_SUCCESS;
+}
+
 /* API: Get the number of sound devices installed in the system. */
 PJ_DEF(unsigned) pjmedia_aud_dev_count(void)
Index: /pjproject/trunk/pjmedia/src/pjmedia-audiodev/coreaudio_dev.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-audiodev/coreaudio_dev.c	(revision 3437)
+++ /pjproject/trunk/pjmedia/src/pjmedia-audiodev/coreaudio_dev.c	(revision 3438)
@@ -179,5 +179,6 @@
     &ca_factory_get_dev_info,
     &ca_factory_default_param,
-    &ca_factory_create_stream
+    &ca_factory_create_stream,
+    &ca_factory_refresh
 };
 
Index: /pjproject/trunk/pjmedia/src/pjmedia-audiodev/legacy_dev.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-audiodev/legacy_dev.c	(revision 3437)
+++ /pjproject/trunk/pjmedia/src/pjmedia-audiodev/legacy_dev.c	(revision 3438)
@@ -52,4 +52,5 @@
 static pj_status_t factory_init(pjmedia_aud_dev_factory *f);
 static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f);
+static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f);
 static unsigned    factory_get_dev_count(pjmedia_aud_dev_factory *f);
 static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f, 
@@ -87,5 +88,6 @@
     &factory_get_dev_info,
     &factory_default_param,
-    &factory_create_stream
+    &factory_create_stream,
+    &factory_refresh
 };
 
@@ -146,4 +148,11 @@
 
     return status;
+}
+
+/* API: refresh the list of devices */
+static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f)
+{
+    PJ_UNUSED_ARG(f);
+    return PJ_ENOTSUP;
 }
 
Index: /pjproject/trunk/pjmedia/src/pjmedia-audiodev/null_dev.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-audiodev/null_dev.c	(revision 3437)
+++ /pjproject/trunk/pjmedia/src/pjmedia-audiodev/null_dev.c	(revision 3438)
@@ -60,4 +60,5 @@
 static pj_status_t null_factory_init(pjmedia_aud_dev_factory *f);
 static pj_status_t null_factory_destroy(pjmedia_aud_dev_factory *f);
+static pj_status_t null_factory_refresh(pjmedia_aud_dev_factory *f);
 static unsigned    null_factory_get_dev_count(pjmedia_aud_dev_factory *f);
 static pj_status_t null_factory_get_dev_info(pjmedia_aud_dev_factory *f,
@@ -94,5 +95,6 @@
     &null_factory_get_dev_info,
     &null_factory_default_param,
-    &null_factory_create_stream
+    &null_factory_create_stream,
+    &null_factory_refresh
 };
 
@@ -164,4 +166,11 @@
     pj_pool_release(pool);
 
+    return PJ_SUCCESS;
+}
+
+/* API: refresh the list of devices */
+static pj_status_t null_factory_refresh(pjmedia_aud_dev_factory *f)
+{
+    PJ_UNUSED_ARG(f);
     return PJ_SUCCESS;
 }
Index: /pjproject/trunk/pjmedia/src/pjmedia-audiodev/pa_dev.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-audiodev/pa_dev.c	(revision 3437)
+++ /pjproject/trunk/pjmedia/src/pjmedia-audiodev/pa_dev.c	(revision 3438)
@@ -107,4 +107,5 @@
 static pj_status_t  pa_init(pjmedia_aud_dev_factory *f);
 static pj_status_t  pa_destroy(pjmedia_aud_dev_factory *f);
+static pj_status_t  pa_refresh(pjmedia_aud_dev_factory *f);
 static unsigned	    pa_get_dev_count(pjmedia_aud_dev_factory *f);
 static pj_status_t  pa_get_dev_info(pjmedia_aud_dev_factory *f, 
@@ -142,5 +143,6 @@
     &pa_get_dev_info,
     &pa_default_param,
-    &pa_create_stream
+    &pa_create_stream,
+    &pa_refresh    
 };
 
@@ -485,4 +487,12 @@
     
     return err ? PJMEDIA_AUDIODEV_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS;
+}
+
+
+/* API: Refresh the device list. */
+static pj_status_t pa_refresh(pjmedia_aud_dev_factory *f)
+{
+    PJ_UNUSED_ARG(f);
+    return PJ_ENOTSUP;
 }
 
Index: /pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp	(revision 3437)
+++ /pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp	(revision 3438)
@@ -121,4 +121,5 @@
 static pj_status_t factory_init(pjmedia_aud_dev_factory *f);
 static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f);
+static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f);
 static unsigned    factory_get_dev_count(pjmedia_aud_dev_factory *f);
 static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f, 
@@ -156,5 +157,6 @@
     &factory_get_dev_info,
     &factory_default_param,
-    &factory_create_stream
+    &factory_create_stream,
+    &factory_refresh
 };
 
@@ -1445,4 +1447,11 @@
 }
 
+/* API: refresh the device list */
+static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f)
+{
+    PJ_UNUSED_ARG(f);
+    return PJ_ENOTSUP;
+}
+
 /* API: get number of devices */
 static unsigned factory_get_dev_count(pjmedia_aud_dev_factory *f)
Index: /pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_mda_dev.cpp
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_mda_dev.cpp	(revision 3437)
+++ /pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_mda_dev.cpp	(revision 3438)
@@ -86,4 +86,5 @@
 static pj_status_t factory_init(pjmedia_aud_dev_factory *f);
 static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f);
+static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f);
 static unsigned    factory_get_dev_count(pjmedia_aud_dev_factory *f);
 static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f, 
@@ -121,5 +122,6 @@
     &factory_get_dev_info,
     &factory_default_param,
-    &factory_create_stream
+    &factory_create_stream,
+    &factory_refresh
 };
 
@@ -833,4 +835,11 @@
     
     return PJ_SUCCESS;
+}
+
+/* API: refresh the device list */
+static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f)
+{
+    PJ_UNUSED_ARG(f);
+    return PJ_ENOTSUP;
 }
 
Index: /pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp	(revision 3437)
+++ /pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp	(revision 3438)
@@ -131,4 +131,5 @@
 static pj_status_t factory_init(pjmedia_aud_dev_factory *f);
 static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f);
+static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f);
 static unsigned    factory_get_dev_count(pjmedia_aud_dev_factory *f);
 static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f, 
@@ -166,5 +167,6 @@
     &factory_get_dev_info,
     &factory_default_param,
-    &factory_create_stream
+    &factory_create_stream,
+    &factory_refresh
 };
 
@@ -1477,4 +1479,11 @@
 }
 
+/* API: refresh the device list */
+static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f)
+{
+    PJ_UNUSED_ARG(f);
+    return PJ_ENOTSUP;
+}
+
 /* API: get number of devices */
 static unsigned factory_get_dev_count(pjmedia_aud_dev_factory *f)
Index: /pjproject/trunk/pjmedia/src/pjmedia-audiodev/wmme_dev.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-audiodev/wmme_dev.c	(revision 3437)
+++ /pjproject/trunk/pjmedia/src/pjmedia-audiodev/wmme_dev.c	(revision 3438)
@@ -39,4 +39,14 @@
 #endif
 
+#ifndef PJMEDIA_WMME_DEV_USE_MMDEVICE_API
+#   define PJMEDIAWMME_DEV_USE_MMDEVICE_API \
+	   (defined(_WIN32_WINNT) && (_WIN32_WINNT>=0x0600))
+#endif
+
+#if PJMEDIA_WMME_DEV_USE_MMDEVICE_API != 0
+#   define DRV_QUERYFUNCTIONINSTANCEID     (DRV_RESERVED + 17)
+#   define DRV_QUERYFUNCTIONINSTANCEIDSIZE (DRV_RESERVED + 18)
+#endif
+
 /* mingw lacks WAVE_FORMAT_ALAW/MULAW */
 #ifndef WAVE_FORMAT_ALAW
@@ -61,4 +71,5 @@
     pjmedia_aud_dev_info	 info;
     unsigned			 deviceId;
+    const wchar_t		*endpointId;
 };
 
@@ -67,4 +78,5 @@
 {
     pjmedia_aud_dev_factory	 base;
+    pj_pool_t			*base_pool;
     pj_pool_t			*pool;
     pj_pool_factory		*pf;
@@ -122,4 +134,5 @@
 static pj_status_t factory_init(pjmedia_aud_dev_factory *f);
 static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f);
+static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f);
 static unsigned    factory_get_dev_count(pjmedia_aud_dev_factory *f);
 static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f, 
@@ -157,5 +170,6 @@
     &factory_get_dev_info,
     &factory_default_param,
-    &factory_create_stream
+    &factory_create_stream,
+    &factory_refresh
 };
 
@@ -182,8 +196,8 @@
     pj_pool_t *pool;
 
-    pool = pj_pool_create(pf, "WMME", 1000, 1000, NULL);
+    pool = pj_pool_create(pf, "WMME base", 1000, 1000, NULL);
     f = PJ_POOL_ZALLOC_T(pool, struct wmme_factory);
     f->pf = pf;
-    f->pool = pool;
+    f->base_pool = pool;
     f->base.op = &factory_op;
 
@@ -191,4 +205,112 @@
 }
 
+/* Internal: Windows Vista and Windows 7 have their device
+ * names truncated when using the waveXXX api.  The names
+ * should be acquired from the MMDevice APIs
+ */
+#if PJMEDIA_WMME_DEV_USE_MMDEVICE_API != 0
+
+#define COBJMACROS
+#include <mmdeviceapi.h>
+#define INITGUID
+#include <Guiddef.h>
+#include <FunctionDiscoveryKeys_devpkey.h>
+
+DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C,
+	    0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E);
+DEFINE_GUID(IID_IMMDeviceEnumerator, 0xA95664D2, 0x9614, 0x4F35,
+	    0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6);
+
+static void get_dev_names(pjmedia_aud_dev_factory *f)
+{
+    struct wmme_factory *wf = (struct wmme_factory*)f;
+    HRESULT              coinit = S_OK;
+    HRESULT              hr = S_OK;
+    IMMDeviceEnumerator *pEnumerator = NULL;
+    IMMDeviceCollection *pDevices = NULL;
+    UINT                 cDevices = 0;
+    UINT                 nDevice = 0;
+
+    coinit = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+    if (coinit == RPC_E_CHANGED_MODE)
+	coinit = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+    if (FAILED(coinit))
+	goto on_error;
+
+    hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL,
+			  CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator,
+			  (void**)&pEnumerator);
+    if (FAILED(hr))
+	goto on_error;
+    hr = IMMDeviceEnumerator_EnumAudioEndpoints(pEnumerator, eAll,
+						DEVICE_STATE_ACTIVE,
+						&pDevices);
+    if (FAILED(hr))
+	goto on_error;
+    hr = IMMDeviceCollection_GetCount(pDevices, &cDevices);
+    if (FAILED(hr))
+	goto on_error;
+
+    for (nDevice = 0; nDevice < cDevices; ++nDevice) {
+	IMMDevice      *pDevice = NULL;
+	IPropertyStore *pProps = NULL;
+	LPWSTR          pwszID = NULL;
+	PROPVARIANT     varName;
+	unsigned        i;
+
+	PropVariantInit(&varName);
+
+	hr = IMMDeviceCollection_Item(pDevices, nDevice, &pDevice);
+	if (FAILED(hr))
+	    goto cleanup;
+	hr = IMMDevice_GetId(pDevice, &pwszID);
+	if (FAILED(hr))
+	    goto cleanup;
+	hr = IMMDevice_OpenPropertyStore(pDevice, STGM_READ, &pProps);
+	if (FAILED(hr))
+	    goto cleanup;
+	hr = IPropertyStore_GetValue(pProps, &PKEY_Device_FriendlyName,
+				     &varName);
+	if (FAILED(hr))
+	    goto cleanup;
+
+	for (i = 0; i < wf->dev_count; ++i) {
+	    if (0 == wcscmp(wf->dev_info[i].endpointId, pwszID)) {
+		wcstombs(wf->dev_info[i].info.name, varName.pwszVal,
+			 sizeof(wf->dev_info[i].info.name));
+		break;
+	    }
+	}
+
+	PropVariantClear(&varName);
+
+    cleanup:
+	if (pProps)
+	    IPropertyStore_Release(pProps);
+	if (pwszID)
+	    CoTaskMemFree(pwszID);
+	if (pDevice)
+	    hr = IMMDevice_Release(pDevice);
+    }
+
+on_error:
+    if (pDevices)
+	hr = IMMDeviceCollection_Release(pDevices);
+
+    if (pEnumerator)
+	hr = IMMDeviceEnumerator_Release(pEnumerator);
+
+    if (SUCCEEDED(coinit))
+	CoUninitialize();
+}
+
+#else
+
+static void get_dev_names(pjmedia_aud_dev_factory *f)
+{
+    PJ_UNUSED_ARG(f);
+}
+
+#endif
 
 /* Internal: build device info from WAVEINCAPS/WAVEOUTCAPS */
@@ -262,4 +384,15 @@
 static pj_status_t factory_init(pjmedia_aud_dev_factory *f)
 {
+    pj_status_t ret = factory_refresh(f);
+    if (ret != PJ_SUCCESS)
+	return ret;
+
+    PJ_LOG(4, (THIS_FILE, "WMME initialized"));
+    return PJ_SUCCESS;
+}
+
+/* API: refresh the device list */
+static pj_status_t factory_refresh(pjmedia_aud_dev_factory *f)
+{
     struct wmme_factory *wf = (struct wmme_factory*)f;
     unsigned c;
@@ -268,6 +401,12 @@
     pj_bool_t waveMapperAdded = PJ_FALSE;
 
+    if (wf->pool != NULL) {
+	pj_pool_release(wf->pool);
+	wf->pool = NULL;
+    }
+
     /* Enumerate sound devices */
     wf->dev_count = 0;
+    wf->pool = pj_pool_create(wf->pf, "WMME", 1000, 1000, NULL);
 
     inputDeviceCount = waveInGetNumDevs();
@@ -315,4 +454,5 @@
 		build_dev_info(WAVE_MAPPER, &wf->dev_info[wf->dev_count], 
 			       &wic, &woc);
+		wf->dev_info[wf->dev_count].endpointId = L"";
 		++wf->dev_count;
 		waveMapperAdded = PJ_TRUE;
@@ -328,4 +468,5 @@
 	    WAVEINCAPS wic;
 	    MMRESULT mr;
+	    DWORD cbEndpointId;
 
 	    pj_bzero(&wic, sizeof(WAVEINCAPS));
@@ -341,4 +482,25 @@
 	    build_dev_info(uDeviceID, &wf->dev_info[wf->dev_count], 
 			   &wic, NULL);
+
+#if PJMEDIA_WMME_DEV_USE_MMDEVICE_API != 0
+	    /* Try to get the endpoint id of the audio device */
+	    wf->dev_info[wf->dev_count].endpointId = L"";
+
+	    mr = waveInMessage((HWAVEIN)IntToPtr(uDeviceID),
+			       DRV_QUERYFUNCTIONINSTANCEIDSIZE,
+			       (DWORD_PTR)&cbEndpointId, (DWORD_PTR)NULL);
+	    if (mr == MMSYSERR_NOERROR) {
+		const wchar_t **epid = &wf->dev_info[wf->dev_count].endpointId;
+		*epid = (const wchar_t*) pj_pool_calloc(wf->pool,
+							cbEndpointId, 1);
+		mr = waveInMessage((HWAVEIN)IntToPtr(uDeviceID),
+				   DRV_QUERYFUNCTIONINSTANCEID,
+				   (DWORD_PTR)*epid,
+				   cbEndpointId);
+	    }
+#else
+	    PJ_UNUSED_ARG(cbEndpointId);
+#endif
+
 	    ++wf->dev_count;
 	}
@@ -352,4 +514,5 @@
 	    WAVEOUTCAPS woc;
 	    MMRESULT mr;
+	    DWORD cbEndpointId;
 
 	    pj_bzero(&woc, sizeof(WAVEOUTCAPS));
@@ -365,9 +528,32 @@
 	    build_dev_info(uDeviceID, &wf->dev_info[wf->dev_count], 
 			   NULL, &woc);
+
+#if PJMEDIA_WMME_DEV_USE_MMDEVICE_API != 0
+	    /* Try to get the endpoint id of the audio device */
+	    wf->dev_info[wf->dev_count].endpointId = L"";
+
+	    mr = waveOutMessage((HWAVEOUT)IntToPtr(uDeviceID),
+				DRV_QUERYFUNCTIONINSTANCEIDSIZE,
+				(DWORD_PTR)&cbEndpointId, (DWORD_PTR)NULL);
+	    if (mr == MMSYSERR_NOERROR) {
+		const wchar_t **epid = &wf->dev_info[wf->dev_count].endpointId;
+		*epid = (const wchar_t*)pj_pool_calloc(wf->pool,
+						       cbEndpointId, 1);
+		mr = waveOutMessage((HWAVEOUT)IntToPtr(uDeviceID),
+				    DRV_QUERYFUNCTIONINSTANCEID,
+				    (DWORD_PTR)*epid, cbEndpointId);
+	    }
+#else
+	    PJ_UNUSED_ARG(cbEndpointId);
+#endif
+
 	    ++wf->dev_count;
 	}
     }
 
-    PJ_LOG(4, (THIS_FILE, "WMME initialized, found %d devices:", 
+    /* On Windows Vista and Windows 7 get the full device names */
+    get_dev_names(f);
+
+    PJ_LOG(4, (THIS_FILE, "WMME found %d devices:",
 	       wf->dev_count));
     for (c = 0; c < wf->dev_count; ++c) {
@@ -386,7 +572,8 @@
 {
     struct wmme_factory *wf = (struct wmme_factory*)f;
-    pj_pool_t *pool = wf->pool;
-
-    wf->pool = NULL;
+    pj_pool_t *pool = wf->base_pool;
+
+    pj_pool_release(wf->pool);
+    wf->base_pool = NULL;
     pj_pool_release(pool);
 
Index: /pjproject/trunk/pjmedia/src/pjmedia/sound_port.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/sound_port.c	(revision 3437)
+++ /pjproject/trunk/pjmedia/src/pjmedia/sound_port.c	(revision 3438)
@@ -49,4 +49,5 @@
     unsigned		 samples_per_frame;
     unsigned		 bits_per_sample;
+    unsigned		 options;
 
     /* software ec */
@@ -278,5 +279,7 @@
 
     /* Start sound stream. */
-    status = pjmedia_aud_stream_start(snd_port->aud_stream);
+    if (!(snd_port->options & PJMEDIA_SND_PORT_NO_AUTO_START)) {
+	status = pjmedia_aud_stream_start(snd_port->aud_stream);
+    }
     if (status != PJ_SUCCESS) {
 	pjmedia_aud_stream_destroy(snd_port->aud_stream);
@@ -325,20 +328,21 @@
 					     pjmedia_snd_port **p_port)
 {
-    pjmedia_aud_param param;
+    pjmedia_snd_port_param param;
     pj_status_t status;
 
     PJ_UNUSED_ARG(options);
 
-    status = pjmedia_aud_dev_default_param(rec_id, &param);
+    status = pjmedia_aud_dev_default_param(rec_id, &param.base);
     if (status != PJ_SUCCESS)
 	return status;
 
-    param.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
-    param.rec_id = rec_id;
-    param.play_id = play_id;
-    param.clock_rate = clock_rate;
-    param.channel_count = channel_count;
-    param.samples_per_frame = samples_per_frame;
-    param.bits_per_sample = bits_per_sample;
+    param.base.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
+    param.base.rec_id = rec_id;
+    param.base.play_id = play_id;
+    param.base.clock_rate = clock_rate;
+    param.base.channel_count = channel_count;
+    param.base.samples_per_frame = samples_per_frame;
+    param.base.bits_per_sample = bits_per_sample;
+    param.options = options;
 
     return pjmedia_snd_port_create2(pool, &param, p_port);
@@ -357,19 +361,20 @@
 						 pjmedia_snd_port **p_port)
 {
-    pjmedia_aud_param param;
+    pjmedia_snd_port_param param;
     pj_status_t status;
 
     PJ_UNUSED_ARG(options);
 
-    status = pjmedia_aud_dev_default_param(dev_id, &param);
+    status = pjmedia_aud_dev_default_param(dev_id, &param.base);
     if (status != PJ_SUCCESS)
 	return status;
 
-    param.dir = PJMEDIA_DIR_CAPTURE;
-    param.rec_id = dev_id;
-    param.clock_rate = clock_rate;
-    param.channel_count = channel_count;
-    param.samples_per_frame = samples_per_frame;
-    param.bits_per_sample = bits_per_sample;
+    param.base.dir = PJMEDIA_DIR_CAPTURE;
+    param.base.rec_id = dev_id;
+    param.base.clock_rate = clock_rate;
+    param.base.channel_count = channel_count;
+    param.base.samples_per_frame = samples_per_frame;
+    param.base.bits_per_sample = bits_per_sample;
+    param.options = options;
 
     return pjmedia_snd_port_create2(pool, &param, p_port);
@@ -389,19 +394,20 @@
 						    pjmedia_snd_port **p_port)
 {
-    pjmedia_aud_param param;
+    pjmedia_snd_port_param param;
     pj_status_t status;
 
     PJ_UNUSED_ARG(options);
 
-    status = pjmedia_aud_dev_default_param(dev_id, &param);
+    status = pjmedia_aud_dev_default_param(dev_id, &param.base);
     if (status != PJ_SUCCESS)
 	return status;
 
-    param.dir = PJMEDIA_DIR_PLAYBACK;
-    param.play_id = dev_id;
-    param.clock_rate = clock_rate;
-    param.channel_count = channel_count;
-    param.samples_per_frame = samples_per_frame;
-    param.bits_per_sample = bits_per_sample;
+    param.base.dir = PJMEDIA_DIR_PLAYBACK;
+    param.base.play_id = dev_id;
+    param.base.clock_rate = clock_rate;
+    param.base.channel_count = channel_count;
+    param.base.samples_per_frame = samples_per_frame;
+    param.base.bits_per_sample = bits_per_sample;
+    param.options = options;
 
     return pjmedia_snd_port_create2(pool, &param, p_port);
@@ -413,5 +419,5 @@
  */
 PJ_DEF(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool,
-					     const pjmedia_aud_param *prm,
+					     const pjmedia_snd_port_param *prm,
 					     pjmedia_snd_port **p_port)
 {
@@ -424,13 +430,14 @@
     PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM);
 
-    snd_port->dir = prm->dir;
-    snd_port->rec_id = prm->rec_id;
-    snd_port->play_id = prm->play_id;
+    snd_port->dir = prm->base.dir;
+    snd_port->rec_id = prm->base.rec_id;
+    snd_port->play_id = prm->base.play_id;
     snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
-    snd_port->clock_rate = prm->clock_rate;
-    snd_port->channel_count = prm->channel_count;
-    snd_port->samples_per_frame = prm->samples_per_frame;
-    snd_port->bits_per_sample = prm->bits_per_sample;
-    pj_memcpy(&snd_port->aud_param, prm, sizeof(*prm));
+    snd_port->clock_rate = prm->base.clock_rate;
+    snd_port->channel_count = prm->base.channel_count;
+    snd_port->samples_per_frame = prm->base.samples_per_frame;
+    snd_port->bits_per_sample = prm->base.bits_per_sample;
+    pj_memcpy(&snd_port->aud_param, prm, sizeof(snd_port->aud_param));
+    snd_port->options = prm->options;
     
     /* Start sound device immediately.
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 3437)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 3438)
@@ -37,5 +37,5 @@
 
 /* Open sound dev */
-static pj_status_t open_snd_dev(pjmedia_aud_param *param);
+static pj_status_t open_snd_dev(pjmedia_snd_port_param *param);
 /* Close existing sound device */
 static void close_snd_dev(void);
@@ -1976,8 +1976,8 @@
 	if (need_reopen) {
 	    if (pjsua_var.cap_dev != NULL_SND_DEV_ID) {
-		pjmedia_aud_param param;
+		pjmedia_snd_port_param param;
 
 		/* Create parameter based on peer info */
-		status = create_aud_param(&param, pjsua_var.cap_dev, 
+		status = create_aud_param(&param.base, pjsua_var.cap_dev, 
 					  pjsua_var.play_dev,
 					  peer_info.clock_rate,
@@ -1992,8 +1992,9 @@
 		/* And peer format */
 		if (peer_info.format.id != PJMEDIA_FORMAT_PCM) {
-		    param.flags |= PJMEDIA_AUD_DEV_CAP_EXT_FORMAT;
-		    param.ext_fmt = peer_info.format;
+		    param.base.flags |= PJMEDIA_AUD_DEV_CAP_EXT_FORMAT;
+		    param.base.ext_fmt = peer_info.format;
 		}
 
+		param.options = 0;
 		status = open_snd_dev(&param);
 		if (status != PJ_SUCCESS) {
@@ -2666,5 +2667,5 @@
 
 /* Open sound device with the setting. */
-static pj_status_t open_snd_dev(pjmedia_aud_param *param)
+static pj_status_t open_snd_dev(pjmedia_snd_port_param *param)
 {
     pjmedia_port *conf_port;
@@ -2674,5 +2675,7 @@
 
     /* Check if NULL sound device is used */
-    if (NULL_SND_DEV_ID==param->rec_id || NULL_SND_DEV_ID==param->play_id) {
+    if (NULL_SND_DEV_ID==param->base.rec_id ||
+	NULL_SND_DEV_ID==param->base.play_id)
+    {
 	return pjsua_set_null_snd_dev();
     }
@@ -2687,11 +2690,11 @@
 
     PJ_LOG(4,(THIS_FILE, "Opening sound device %s@%d/%d/%dms",
-	      get_fmt_name(param->ext_fmt.id),
-	      param->clock_rate, param->channel_count,
-	      param->samples_per_frame / param->channel_count * 1000 /
-	      param->clock_rate));
+	      get_fmt_name(param->base.ext_fmt.id),
+	      param->base.clock_rate, param->base.channel_count,
+	      param->base.samples_per_frame / param->base.channel_count *
+	      1000 / param->base.clock_rate));
 
     status = pjmedia_snd_port_create2( pjsua_var.snd_pool, 
-				       param,  &pjsua_var.snd_port);
+				       param, &pjsua_var.snd_port);
     if (status != PJ_SUCCESS)
 	return status;
@@ -2705,6 +2708,6 @@
      */
     if (!pjsua_var.is_mswitch &&
-	param->ext_fmt.id == PJMEDIA_FORMAT_PCM &&
-	conf_port->info.clock_rate != param->clock_rate)
+	param->base.ext_fmt.id == PJMEDIA_FORMAT_PCM &&
+	conf_port->info.clock_rate != param->base.clock_rate)
     {
 	pjmedia_port *resample_port;
@@ -2722,5 +2725,5 @@
 	status = pjmedia_resample_port_create(pjsua_var.snd_pool, 
 					      conf_port,
-					      param->clock_rate,
+					      param->base.clock_rate,
 					      resample_opt, 
 					      &resample_port);
@@ -2742,9 +2745,9 @@
      */
     if (pjsua_var.is_mswitch) {
-	pj_memcpy(&conf_port->info.format, &param->ext_fmt, 
+	pj_memcpy(&conf_port->info.format, &param->base.ext_fmt, 
 		  sizeof(conf_port->info.format));
-	conf_port->info.clock_rate = param->clock_rate;
-	conf_port->info.samples_per_frame = param->samples_per_frame;
-	conf_port->info.channel_count = param->channel_count;
+	conf_port->info.clock_rate = param->base.clock_rate;
+	conf_port->info.samples_per_frame = param->base.samples_per_frame;
+	conf_port->info.channel_count = param->base.channel_count;
 	conf_port->info.bits_per_sample = 16;
     }
@@ -2762,6 +2765,6 @@
 
     /* Save the device IDs */
-    pjsua_var.cap_dev = param->rec_id;
-    pjsua_var.play_dev = param->play_id;
+    pjsua_var.cap_dev = param->base.rec_id;
+    pjsua_var.play_dev = param->base.play_id;
 
     /* Update sound device name. */
@@ -2778,5 +2781,5 @@
 
 	if (status==PJ_SUCCESS) {
-	    if (param->clock_rate != pjsua_var.media_cfg.clock_rate) {
+	    if (param->base.clock_rate != pjsua_var.media_cfg.clock_rate) {
 		char tmp_buf[128];
 		int tmp_buf_len = sizeof(tmp_buf);
@@ -2785,5 +2788,5 @@
 					       "%s (%dKHz)",
 					       rec_info.name, 
-					       param->clock_rate/1000);
+					       param->base.clock_rate/1000);
 		pj_strset(&tmp, tmp_buf, tmp_buf_len);
 		pjmedia_conf_set_port0_name(pjsua_var.mconf, &tmp); 
@@ -2884,5 +2887,5 @@
     /* Attempts to open the sound device with different clock rates */
     for (i=0; i<alt_cr_cnt; ++i) {
-	pjmedia_aud_param param;
+	pjmedia_snd_port_param param;
 	unsigned samples_per_frame;
 
@@ -2891,5 +2894,5 @@
 			    pjsua_var.media_cfg.audio_frame_ptime *
 			    pjsua_var.media_cfg.channel_count / 1000;
-	status = create_aud_param(&param, capture_dev, playback_dev, 
+	status = create_aud_param(&param.base, capture_dev, playback_dev, 
 				  alt_cr[i], pjsua_var.media_cfg.channel_count,
 				  samples_per_frame, 16);
@@ -2898,4 +2901,5 @@
 
 	/* Open! */
+	param.options = 0;
 	status = open_snd_dev(&param);
 	if (status == PJ_SUCCESS)
