Index: pjproject/trunk/pjmedia/src/pjmedia/sound_port.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/sound_port.c	(revision 3999)
+++ pjproject/trunk/pjmedia/src/pjmedia/sound_port.c	(revision 4082)
@@ -53,4 +53,5 @@
     unsigned		 bits_per_sample;
     unsigned		 options;
+    unsigned		 prm_ec_options;
 
     /* software ec */
@@ -188,4 +189,10 @@
 }
 
+/* Initialize with default values (zero) */
+PJ_DEF(void) pjmedia_snd_port_param_default(pjmedia_snd_port_param *prm)
+{
+    pj_bzero(prm, sizeof(*prm));
+}
+
 /*
  * Start the sound stream.
@@ -227,9 +234,12 @@
     if (param_copy.flags & PJMEDIA_AUD_DEV_CAP_EC) {
 	/* EC is wanted */
-	if (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC) {
+	if ((snd_port->prm_ec_options & PJMEDIA_ECHO_USE_SW_ECHO) == 0 &&
+            snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC)
+        {
 	    /* Device supports EC */
 	    /* Nothing to do */
 	} else {
-	    /* Device doesn't support EC, remove EC settings from
+	    /* Application wants to use software EC or device
+             * doesn't support EC, remove EC settings from
 	     * device parameters
 	     */
@@ -263,9 +273,11 @@
 				  snd_port->samples_per_frame);
 
-    /* Create software EC if parameter specifies EC but device 
-     * doesn't support EC. Only do this if the format is PCM!
+    /* Create software EC if parameter specifies EC and
+     * (app specifically requests software EC or device
+     * doesn't support EC). Only do this if the format is PCM!
      */
     if ((snd_port->aud_param.flags & PJMEDIA_AUD_DEV_CAP_EC) &&
-	(snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC)==0 &&
+	((snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC)==0 ||
+         (snd_port->prm_ec_options & PJMEDIA_ECHO_USE_SW_ECHO) != 0) &&
 	param_copy.ext_fmt.id == PJMEDIA_FORMAT_PCM)
     {
@@ -278,5 +290,6 @@
 	    
 	status = pjmedia_snd_port_set_ec(snd_port, pool, 
-					 snd_port->aud_param.ec_tail_ms, 0);
+					 snd_port->aud_param.ec_tail_ms,
+					 snd_port->prm_ec_options);
 	if (status != PJ_SUCCESS) {
 	    pjmedia_aud_stream_destroy(snd_port->aud_stream);
@@ -339,5 +352,5 @@
     pj_status_t status;
 
-    PJ_UNUSED_ARG(options);
+    pjmedia_snd_port_param_default(&param);
 
     status = pjmedia_aud_dev_default_param(rec_id, &param.base);
@@ -353,4 +366,5 @@
     param.base.bits_per_sample = bits_per_sample;
     param.options = options;
+    param.ec_options = 0;
 
     return pjmedia_snd_port_create2(pool, &param, p_port);
@@ -372,5 +386,5 @@
     pj_status_t status;
 
-    PJ_UNUSED_ARG(options);
+    pjmedia_snd_port_param_default(&param);
 
     status = pjmedia_aud_dev_default_param(dev_id, &param.base);
@@ -385,4 +399,5 @@
     param.base.bits_per_sample = bits_per_sample;
     param.options = options;
+    param.ec_options = 0;
 
     return pjmedia_snd_port_create2(pool, &param, p_port);
@@ -405,5 +420,5 @@
     pj_status_t status;
 
-    PJ_UNUSED_ARG(options);
+    pjmedia_snd_port_param_default(&param);
 
     status = pjmedia_aud_dev_default_param(dev_id, &param.base);
@@ -418,4 +433,5 @@
     param.base.bits_per_sample = bits_per_sample;
     param.options = options;
+    param.ec_options = 0;
 
     return pjmedia_snd_port_create2(pool, &param, p_port);
@@ -446,6 +462,7 @@
     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));
+    pj_memcpy(&snd_port->aud_param, &prm->base, sizeof(snd_port->aud_param));
     snd_port->options = prm->options;
+    snd_port->prm_ec_options = prm->ec_options;
 
     ptime_usec = prm->base.samples_per_frame * 1000 / prm->base.channel_count /
@@ -510,5 +527,7 @@
 
     /* Determine whether we use device or software EC */
-    if (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC) {
+    if ((snd_port->prm_ec_options & PJMEDIA_ECHO_USE_SW_ECHO) == 0 &&
+        snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC)
+    {
 	/* We use device EC */
 	pj_bool_t ec_enabled;
