Index: /pjproject/trunk/pjmedia/include/pjmedia/sound_port.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/sound_port.h	(revision 730)
+++ /pjproject/trunk/pjmedia/include/pjmedia/sound_port.h	(revision 731)
@@ -221,4 +221,10 @@
 
 
+/**
+ * Enable or disable echo canceller. By default the EC is enabled after it
+ * was created, so there is no need to enable the EC after creating it.
+ * This function is only useful to disable the echo canceller temporarily,
+ * for example during idle period, to prevent EC from using
+ */
 
 /**
Index: /pjproject/trunk/pjmedia/src/pjmedia/conference.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 730)
+++ /pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 731)
@@ -1267,5 +1267,6 @@
  */
 static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport,
-			      pj_uint32_t timestamp)
+			      pj_uint32_t timestamp, 
+			      pjmedia_frame_type *frm_type)
 {
     pj_int16_t *buf;
@@ -1273,4 +1274,6 @@
     pj_status_t status;
 
+    *frm_type = PJMEDIA_FRAME_TYPE_AUDIO;
+
     /* If port is muted or nobody is transmitting to this port, 
      * transmit NULL frame. 
@@ -1293,8 +1296,10 @@
 
 	cport->tx_level = 0;
+	*frm_type = PJMEDIA_FRAME_TYPE_NONE;
 	return PJ_SUCCESS;
 
     } else if (cport->tx_setting != PJMEDIA_PORT_ENABLE) {
 	cport->tx_level = 0;
+	*frm_type = PJMEDIA_FRAME_TYPE_NONE;
 	return PJ_SUCCESS;
     }
@@ -1487,4 +1492,5 @@
 {
     pjmedia_conf *conf = this_port->port_data.pdata;
+    pjmedia_frame_type speaker_frame_type = PJMEDIA_FRAME_TYPE_NONE;
     unsigned ci, cj, i, j;
     
@@ -1684,4 +1690,5 @@
     for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) {
 	struct conf_port *conf_port = conf->ports[i];
+	pjmedia_frame_type frm_type;
 	pj_status_t status;
 
@@ -1692,5 +1699,6 @@
 	++ci;
 
-	status = write_port( conf, conf_port, frame->timestamp.u32.lo);
+	status = write_port( conf, conf_port, frame->timestamp.u32.lo,
+			     &frm_type);
 	if (status != PJ_SUCCESS) {
 	    /* bennylp: why do we need this????
@@ -1709,4 +1717,10 @@
 	    continue;
 	}
+
+	/* Set the type of frame to be returned to sound playback
+	 * device.
+	 */
+	if (i == 0)
+	    speaker_frame_type = frm_type;
     }
 
@@ -1723,5 +1737,5 @@
 
     /* MUST set frame type */
-    frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
+    frame->type = speaker_frame_type;
 
     pj_mutex_unlock(conf->mutex);
@@ -1745,4 +1759,6 @@
 {
     pj_assert(0);
+    PJ_UNUSED_ARG(this_port);
+    PJ_UNUSED_ARG(frame);
     return -1;
 }
Index: /pjproject/trunk/pjmedia/src/pjmedia/port.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/port.c	(revision 730)
+++ /pjproject/trunk/pjmedia/src/pjmedia/port.c	(revision 731)
@@ -63,7 +63,11 @@
 {
     PJ_ASSERT_RETURN(port && frame, PJ_EINVAL);
-    PJ_ASSERT_RETURN(port->get_frame, PJ_EINVALIDOP);
 
-    return port->get_frame(port, frame);
+    if (port->get_frame)
+	return port->get_frame(port, frame);
+    else {
+	frame->type = PJMEDIA_FRAME_TYPE_NONE;
+	return PJ_EINVALIDOP;
+    }
 }
 
@@ -76,8 +80,9 @@
 {
     PJ_ASSERT_RETURN(port && frame, PJ_EINVAL);
-    PJ_ASSERT_RETURN(port->put_frame, PJ_EINVALIDOP);
 
-    return port->put_frame(port, frame);
-
+    if (port->put_frame)
+	return port->put_frame(port, frame);
+    else
+	return PJ_EINVALIDOP;
 }
 
Index: /pjproject/trunk/pjmedia/src/pjmedia/sound_port.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/sound_port.c	(revision 730)
+++ /pjproject/trunk/pjmedia/src/pjmedia/sound_port.c	(revision 731)
@@ -35,5 +35,6 @@
 
 //#define SIMULATE_LOST_PCT   20
-#define AEC_TAIL    128	    /* default AEC length in ms */
+#define AEC_TAIL	    128	    /* default AEC length in ms */
+#define AEC_SUSPEND_LIMIT   5	    /* seconds of no activity	*/
 
 #define THIS_FILE	    "sound_port.c"
@@ -59,4 +60,9 @@
     pjmedia_echo_state	*ec_state;
     unsigned		 aec_tail_len;
+
+    pj_bool_t		 ec_suspended;
+    unsigned		 ec_suspend_count;
+    unsigned		 ec_suspend_limit;
+
     pjmedia_plc		*plc;
 
@@ -117,4 +123,9 @@
 
     if (snd_port->ec_state) {
+	if (snd_port->ec_suspended) {
+	    snd_port->ec_suspended = PJ_FALSE;
+	    PJ_LOG(4,(THIS_FILE, "EC activated"));
+	}
+	snd_port->ec_suspend_count = 0;
 	pjmedia_echo_playback(snd_port->ec_state, output);
     }
@@ -124,4 +135,12 @@
 
 no_frame:
+
+    if (!snd_port->ec_suspended) {
+	++snd_port->ec_suspend_count;
+	if (snd_port->ec_suspend_count > snd_port->ec_suspend_limit) {
+	    snd_port->ec_suspended = PJ_TRUE;
+	    PJ_LOG(4,(THIS_FILE, "EC suspended because of inactivity"));
+	}
+    }
 
     /* Apply PLC */
@@ -165,5 +184,5 @@
 
     /* Cancel echo */
-    if (snd_port->ec_state) {
+    if (snd_port->ec_state && !snd_port->ec_suspended) {
 	pjmedia_echo_capture(snd_port->ec_state, input, 0);
     }
@@ -254,4 +273,8 @@
     }
 
+    /* Inactivity limit before EC is suspended. */
+    snd_port->ec_suspend_limit = AEC_SUSPEND_LIMIT *
+				 (snd_port->clock_rate / 
+				  snd_port->samples_per_frame);
 
     /* Start sound stream. */
@@ -455,4 +478,6 @@
 	if (status != PJ_SUCCESS)
 	    snd_port->ec_state = NULL;
+	else
+	    snd_port->ec_suspended = PJ_FALSE;
     } else {
 	PJ_LOG(4,(THIS_FILE, "Echo canceller is now disabled in the "
Index: /pjproject/trunk/pjmedia/src/pjmedia/wav_player.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/wav_player.c	(revision 730)
+++ /pjproject/trunk/pjmedia/src/pjmedia/wav_player.c	(revision 731)
@@ -71,6 +71,4 @@
 
 
-static pj_status_t file_put_frame(pjmedia_port *this_port, 
-				  const pjmedia_frame *frame);
 static pj_status_t file_get_frame(pjmedia_port *this_port, 
 				  pjmedia_frame *frame);
@@ -92,5 +90,4 @@
 			   8000, 1, 16, 80);
 
-    port->base.put_frame = &file_put_frame;
     port->base.get_frame = &file_get_frame;
     port->base.on_destroy = &file_on_destroy;
@@ -470,15 +467,4 @@
 
 /*
- * Put frame to file.
- */
-static pj_status_t file_put_frame(pjmedia_port *this_port, 
-				  const pjmedia_frame *frame)
-{
-    PJ_UNUSED_ARG(this_port);
-    PJ_UNUSED_ARG(frame);
-    return PJ_EINVALIDOP;
-}
-
-/*
  * Get frame from file.
  */
Index: /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 730)
+++ /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 731)
@@ -2188,5 +2188,5 @@
      * Echo canceller tail length, in miliseconds.
      *
-     * Default: 128 (PJSUA_DEFAULT_EC_TAIL_LEN)
+     * Default: PJSUA_DEFAULT_EC_TAIL_LEN
      */
     unsigned		ec_tail_len;
