Index: pjproject/trunk/pjmedia/build/pjmedia.dsp
===================================================================
--- pjproject/trunk/pjmedia/build/pjmedia.dsp	(revision 228)
+++ pjproject/trunk/pjmedia/build/pjmedia.dsp	(revision 229)
@@ -66,5 +66,5 @@
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../src/pjmedia/portaudio" /D "_DEBUG" /D "PA_NO_ASIO" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c
+# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../src/pjmedia/portaudio" /D "_DEBUG" /D "PA_NO_ASIO" /D "PA_NO_WMME" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c
 # SUBTRACT CPP /YX
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
Index: pjproject/trunk/pjmedia/include/pjmedia/silencedet.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/silencedet.h	(revision 228)
+++ pjproject/trunk/pjmedia/include/pjmedia/silencedet.h	(revision 229)
@@ -86,18 +86,7 @@
 
 /**
- * Calculate average signal level for the given samples.
- *
- * @param samples	Pointer to 16-bit PCM samples.
- * @param count		Number of samples in the input.
- *
- * @return		The average signal level, which simply is total level
- *			divided by number of samples.
- */
-PJ_DECL(pj_int32_t) pjmedia_silence_det_calc_avg_signal( const pj_int16_t samples[],
-							 pj_size_t count );
-
-
-/**
- * Perform voice activity detection on the given input samples.
+ * Perform voice activity detection on the given input samples. This
+ * function uses #pjmedia_calc_avg_signal() and #pjmedia_silence_det_apply()
+ * for its calculation.
  *
  * @param sd		The silence detector instance.
@@ -109,8 +98,35 @@
  * @return		PJ_SUCCESS on success.
  */
-PJ_DECL(pj_bool_t) pjmedia_silence_det_detect_silence( pjmedia_silence_det *sd,
-						       const pj_int16_t samples[],
-						       pj_size_t count,
-						       pj_int32_t *p_level);
+PJ_DECL(pj_bool_t) pjmedia_silence_det_detect( pjmedia_silence_det *sd,
+					       const pj_int16_t samples[],
+					       pj_size_t count,
+					       pj_int32_t *p_level);
+
+
+/**
+ * Calculate average signal level for the given samples.
+ *
+ * @param samples	Pointer to 16-bit PCM samples.
+ * @param count		Number of samples in the input.
+ *
+ * @return		The average signal level, which simply is total level
+ *			divided by number of samples.
+ */
+PJ_DECL(pj_int32_t) pjmedia_calc_avg_signal( const pj_int16_t samples[],
+					     pj_size_t count );
+
+
+
+/**
+ * Perform voice activity detection, given the specified average signal
+ * level.
+ *
+ * @param sd		The silence detector instance.
+ * @param level		Signal level.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_bool_t) pjmedia_silence_det_apply( pjmedia_silence_det *sd,
+					      pj_uint32_t level);
 
 
Index: pjproject/trunk/pjmedia/src/pjmedia/conference.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 228)
+++ pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 229)
@@ -92,4 +92,5 @@
     pj_snd_stream	 *snd_rec;	/**< Sound recorder stream.	    */
     pj_snd_stream	 *snd_player;	/**< Sound player stream.	    */
+    pj_mutex_t		 *mutex;	/**< Conference mutex.		    */
     struct conf_port	**ports;	/**< Array of ports.		    */
     pj_uint16_t		 *uns_buf;	/**< Buf for unsigned conversion    */
@@ -100,4 +101,7 @@
 };
 
+
+/* Extern */
+unsigned char linear2ulaw(int pcm_val);
 
 /* Prototypes */
@@ -261,4 +265,11 @@
     conf->uns_buf = pj_pool_zalloc(pool, samples_per_frame *
 					 sizeof(conf->uns_buf[0]));
+
+    /* Create mutex. */
+    status = pj_mutex_create_simple(pool, "conf", &conf->mutex);
+    if (status != PJ_SUCCESS)
+	return status;
+
+
     /* Done */
 
@@ -365,4 +376,5 @@
     suspend_sound(conf);
     destroy_sound(conf);
+    pj_mutex_destroy(conf->mutex);
 
     return PJ_SUCCESS;
@@ -386,6 +398,9 @@
 		     PJ_EINVAL);
 
+    pj_mutex_lock(conf->mutex);
+
     if (conf->port_cnt >= conf->max_ports) {
 	pj_assert(!"Too many ports");
+	pj_mutex_unlock(conf->mutex);
 	return PJ_ETOOMANY;
     }
@@ -401,6 +416,8 @@
     /* Create port structure. */
     status = create_conf_port(pool, conf, port_name, &conf_port);
-    if (status != PJ_SUCCESS)
+    if (status != PJ_SUCCESS) {
+	pj_mutex_unlock(conf->mutex);
 	return status;
+    }
 
     /* Set the port */
@@ -413,4 +430,6 @@
     /* Done. */
     *p_port = index;
+
+    pj_mutex_unlock(conf->mutex);
 
     return PJ_SUCCESS;
@@ -462,4 +481,6 @@
     PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL);
     PJ_ASSERT_RETURN(conf->ports[sink_slot] != NULL, PJ_EINVAL);
+
+    pj_mutex_lock(conf->mutex);
 
     src_port = conf->ports[src_slot];
@@ -481,4 +502,6 @@
     }
 
+    pj_mutex_unlock(conf->mutex);
+
     return PJ_SUCCESS;
 }
@@ -501,4 +524,6 @@
     PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL);
     PJ_ASSERT_RETURN(conf->ports[sink_slot] != NULL, PJ_EINVAL);
+
+    pj_mutex_lock(conf->mutex);
 
     src_port = conf->ports[src_slot];
@@ -522,4 +547,6 @@
     }
 
+    pj_mutex_unlock(conf->mutex);
+
     return PJ_SUCCESS;
 }
@@ -545,5 +572,6 @@
      * device's threads!
      */
-    //suspend_sound(conf);
+
+    pj_mutex_lock(conf->mutex);
 
     conf_port = conf->ports[port];
@@ -578,12 +606,11 @@
     --conf->port_cnt;
 
-    /* Reactivate sound device if there are connections */
-    if (conf->connect_cnt != 0) {
-    	//resume_sound(conf);
-    } else {
+    /* Stop sound if there's no connection. */
+    if (conf->connect_cnt == 0) {
 	destroy_sound(conf);
     }
 
-    pj_thread_sleep(60);
+    pj_mutex_unlock(conf->mutex);
+
     return PJ_SUCCESS;
 }
@@ -659,5 +686,5 @@
     pjmedia_conf *conf = user_data;
     pj_int16_t *output_buf = output;
-    unsigned i, j;
+    unsigned ci, cj, i, j;
     
     PJ_UNUSED_ARG(timestamp);
@@ -666,11 +693,16 @@
     TRACE_(("p"));
 
-    /* Clear all port's tmp buffers. */
-    for (i=0; i<conf->max_ports; ++i) {
+    pj_mutex_lock(conf->mutex);
+
+    /* Zero all port's temporary buffers. */
+    for (i=0, ci=0; i<conf->max_ports && ci < conf->port_cnt; ++i) {
 	struct conf_port *conf_port = conf->ports[i];
 	pj_uint32_t *sum_buf;
 
+	/* Skip empty slot. */
 	if (!conf_port)
 	    continue;
+
+	++ci;
 
 	conf_port->sources = 0;
@@ -681,11 +713,10 @@
     }
 
-    /* Get frames from all ports, and "add" the signal 
+    /* Get frames from all ports, and "mix" the signal 
      * to sum_buf of all listeners of the port.
      */
-    for (i=0; i<conf->max_ports; ++i) {
+    for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) {
 	struct conf_port *conf_port = conf->ports[i];
 	pj_int32_t level;
-	pj_bool_t silence;
 
 	/* Skip empty port. */
@@ -693,13 +724,14 @@
 	    continue;
 
+	++ci;
+
 	/* Skip if we're not allowed to receive from this port. */
 	if (conf_port->rx_setting == PJMEDIA_PORT_DISABLE) {
-	    TRACE_(("rxdis:%d ", i));
 	    continue;
 	}
 
 	/* Get frame from this port. 
-	 * If port has rx_buffer (e.g. sound port), then get the frame 
-	 * from the rx_buffer instead.
+	 * For port zero (sound port), get the frame  from the rx_buffer
+	 * instead.
 	 */
 	if (i==0) {
@@ -712,4 +744,15 @@
 	    }
 
+	    /* Skip if this port is muted/disabled. */
+	    if (conf_port->rx_setting != PJMEDIA_PORT_ENABLE) {
+		continue;
+	    }
+
+
+	    /* Skip if no port is listening to the microphone */
+	    if (conf_port->listener_cnt == 0) {
+		continue;
+	    }
+
 	    rx_buf = conf_port->rx_buf[conf_port->rx_read];
 	    for (j=0; j<conf->samples_per_frame; ++j) {
@@ -726,5 +769,5 @@
 	    pjmedia_port_get_frame(conf_port->port, &frame);
 
-	    if (frame.type == PJMEDIA_FRAME_TYPE_NONE)
+	   if (frame.type == PJMEDIA_FRAME_TYPE_NONE)
 		continue;
 	}
@@ -738,22 +781,19 @@
 	    continue;
 
-	/* Do we have signal? */
-	silence = pjmedia_silence_det_detect_silence(conf_port->vad,
-						     output, 
-						     conf->samples_per_frame,
-						     &level);
-
-	/* Skip if we don't have signal. */
-	if (silence) {
-	    TRACE_(("sil:%d ", i));
-	    continue;
-	}
-
-	/* Convert the buffer to unsigned value */
+	/* Get the signal level. */
+	level = pjmedia_calc_avg_signal(output, conf->samples_per_frame);
+
+	/* Convert level to 8bit complement ulaw */
+	level = linear2ulaw(level) ^ 0xff;
+
+	/* Convert the buffer to unsigned 16bit value */
 	for (j=0; j<conf->samples_per_frame; ++j)
 	    conf->uns_buf[j] = pcm2unsigned(((pj_int16_t*)output)[j]);
 
 	/* Add the signal to all listeners. */
-	for (j=0; j<conf->max_ports; ++j) {
+	for (j=0, cj=0; 
+	     j<conf->max_ports && cj<(unsigned)conf_port->listener_cnt;
+	     ++j) 
+	{
 	    struct conf_port *listener = conf->ports[j];
 	    pj_uint32_t *sum_buf;
@@ -763,20 +803,25 @@
 		continue;
 
+	    /* Skip if this is not the listener. */
+	    if (!conf_port->listeners[j])
+		continue;
+
+	    ++cj;
+
 	    /* Skip if this listener doesn't want to receive audio */
 	    if (listener->tx_setting != PJMEDIA_PORT_ENABLE)
 		continue;
 
-	    //TRACE_(("mix:%d->%d ", i, j));
-
+	    /* Mix the buffer */
 	    sum_buf = listener->sum_buf;
 	    for (k=0; k<conf->samples_per_frame; ++k)
-		sum_buf[k] += conf->uns_buf[k];
-
-	    listener->sources++;
+		sum_buf[k] += (conf->uns_buf[k] * level);
+
+	    listener->sources += level;
 	}
     }
 
     /* For all ports, calculate avg signal. */
-    for (i=0; i<conf->max_ports; ++i) {
+    for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) {
 	struct conf_port *conf_port = conf->ports[i];
 	pjmedia_frame frame;
@@ -785,4 +830,6 @@
 	if (!conf_port)
 	    continue;
+
+	++ci;
 
 	if (conf_port->tx_setting == PJMEDIA_PORT_MUTE) {
@@ -800,12 +847,4 @@
 	}
 
-	//
-	// TODO:
-	//  When there's no source, not transmit the frame, but instead
-	//  transmit a 'silence' frame. This is to allow the 'port' to
-	//  do some processing, such as updating timestamp for RTP session
-	//  or transmit signal when it's in the middle of transmitting DTMF.
-	//
-
 	target_buf = (conf_port->cur_tx_buf==conf_port->tx_buf1?
 			conf_port->tx_buf2 : conf_port->tx_buf1);
@@ -813,5 +852,6 @@
 	if (conf_port->sources) {
 	    for (j=0; j<conf->samples_per_frame; ++j) {
-		target_buf[j] = unsigned2pcm(conf_port->sum_buf[j] / conf_port->sources);
+		target_buf[j] = unsigned2pcm(conf_port->sum_buf[j] / 
+					     conf_port->sources);
 	    }
 	}
@@ -821,7 +861,19 @@
 
 	pj_memset(&frame, 0, sizeof(frame));
-	if (conf_port->sources)
-	    frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
-	else
+	if (conf_port->sources) {
+
+	    pj_bool_t is_silence = PJ_FALSE;
+
+	    /* Apply silence detection. */
+#if 0
+	    is_silence = pjmedia_silence_det_detect(conf_port->vad,
+						    target_buf,
+						    conf->samples_per_frame,
+						    NULL);
+#endif
+	    frame.type = is_silence ? PJMEDIA_FRAME_TYPE_NONE : 
+				      PJMEDIA_FRAME_TYPE_AUDIO;
+
+	} else
 	    frame.type = PJMEDIA_FRAME_TYPE_NONE;
 
@@ -836,6 +888,13 @@
 
     /* Return sound playback frame. */
-    for (j=0; j<conf->samples_per_frame; ++j)
-	output_buf[j] = conf->ports[0]->cur_tx_buf[j];
+    if (conf->ports[0]->sources) {
+	for (j=0; j<conf->samples_per_frame; ++j)
+	    output_buf[j] = conf->ports[0]->cur_tx_buf[j];
+    } else {
+	for (j=0; j<conf->samples_per_frame; ++j)
+	    output_buf[j] = 0;
+    }
+
+    pj_mutex_unlock(conf->mutex);
 
     return PJ_SUCCESS;
@@ -863,4 +922,12 @@
 	TRACE_(("rxerr "));
     }
+
+    /* Skip if this port is muted/disabled. */
+    if (snd_port->rx_setting != PJMEDIA_PORT_ENABLE)
+	return PJ_SUCCESS;
+
+    /* Skip if no port is listening to the microphone */
+    if (snd_port->listener_cnt == 0)
+	return PJ_SUCCESS;
 
 
Index: pjproject/trunk/pjmedia/src/pjmedia/jbuf.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/jbuf.c	(revision 228)
+++ pjproject/trunk/pjmedia/src/pjmedia/jbuf.c	(revision 229)
@@ -24,6 +24,9 @@
 #include <pj/pool.h>
 #include <pj/assert.h>
+#include <pj/log.h>
 #include <pj/string.h>
 
+
+#define THIS_FILE   "jbuf.c"
 
 
@@ -55,4 +58,5 @@
     int		    jb_max_hist_jitter;   // max jitter	during the last	jitter calculations
     int		    jb_stable_hist;	  // num of times the delay has	been lower then	the prefetch num
+    unsigned	    jb_op_count;	  // of of operations.
     int		    jb_last_op;		  // last operation executed on	the framelist->flist_buffer (put/get)
     int		    jb_last_seq_no;	  // seq no. of	the last frame inserted	to the framelist->flist_buffer
@@ -293,6 +297,7 @@
     jb->jb_last_level = jb->jb_level;
     jb->jb_max_hist_jitter = PJ_MAX(jb->jb_max_hist_jitter,jb->jb_last_jitter);
-    
-    if (jb->jb_last_jitter< jb->jb_prefetch) {
+    jb->jb_op_count++;
+
+    if (jb->jb_last_jitter < jb->jb_prefetch) {
 	jb->jb_stable_hist += jb->jb_last_jitter;
 	if (jb->jb_stable_hist > STABLE_HISTORY_LIMIT) {
@@ -305,4 +310,16 @@
 	    jb->jb_stable_hist = 0;
 	    jb->jb_max_hist_jitter = 0;
+
+	    if (jb->jb_op_count >= 100 &&
+		(int)jb_framelist_size(&jb->jb_framelist) > jb->jb_prefetch+2) 
+	    {
+		jb_framelist_remove_head(&jb->jb_framelist,1);
+
+		PJ_LOG(5,(THIS_FILE, "jbuf prefetch: %d, size=%d", 
+				 jb->jb_prefetch,
+				 jb_framelist_size(&jb->jb_framelist)));
+		jb->jb_op_count = 0;
+	    }
+
 	}
     } else {
@@ -310,4 +327,16 @@
 	jb->jb_stable_hist = 0;
 	jb->jb_max_hist_jitter = 0;
+
+	if (jb->jb_op_count >= 100) {
+	    if ((int)jb_framelist_size(&jb->jb_framelist) > jb->jb_prefetch+2) {
+		jb_framelist_remove_head(&jb->jb_framelist,1);
+
+		PJ_LOG(5,(THIS_FILE, "jbuf prefetch: %d, size=%d", 
+				 jb->jb_prefetch,
+				 jb_framelist_size(&jb->jb_framelist)));
+	    }
+
+	    jb->jb_op_count = 0;
+	}
     }
 }
Index: pjproject/trunk/pjmedia/src/pjmedia/silencedet.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/silencedet.c	(revision 228)
+++ pjproject/trunk/pjmedia/src/pjmedia/silencedet.c	(revision 229)
@@ -120,6 +120,6 @@
 
 
-PJ_DEF(pj_int32_t) pjmedia_silence_det_calc_avg_signal(const pj_int16_t samples[],
-						       pj_size_t count)
+PJ_DEF(pj_int32_t) pjmedia_calc_avg_signal( const pj_int16_t samples[],
+					    pj_size_t count)
 {
     pj_uint32_t sum = 0;
@@ -141,25 +141,12 @@
 }
 
-PJ_DEF(pj_bool_t) pjmedia_silence_det_detect_silence( pjmedia_silence_det *sd,
-						      const pj_int16_t samples[],
-						      pj_size_t count,
-						      pj_int32_t *p_level)
-{
-    pj_uint32_t level;
+PJ_DEF(pj_bool_t) pjmedia_silence_det_apply( pjmedia_silence_det *sd,
+					     pj_uint32_t level)
+{
     pj_bool_t have_signal;
 
     /* Always return false if VAD is disabled */
-    if (sd->mode == VAD_MODE_NONE) {
-	if (p_level)
-	    *p_level = -1;
+    if (sd->mode == VAD_MODE_NONE)
 	return PJ_FALSE;
-    }
-    
-    /* Calculate average signal level. */
-    level = pjmedia_silence_det_calc_avg_signal(samples, count);
-    
-    /* Report to caller, if required. */
-    if (p_level)
-	*p_level = level;
 
     /* Convert PCM level to ulaw */
@@ -266,4 +253,23 @@
     
     return !sd->in_talk;
-}
-
+
+}
+
+
+PJ_DEF(pj_bool_t) pjmedia_silence_det_detect( pjmedia_silence_det *sd,
+					      const pj_int16_t samples[],
+					      pj_size_t count,
+					      pj_int32_t *p_level)
+{
+    pj_uint32_t level;
+    
+    /* Calculate average signal level. */
+    level = pjmedia_calc_avg_signal(samples, count);
+    
+    /* Report to caller, if required. */
+    if (p_level)
+	*p_level = level;
+
+    return pjmedia_silence_det_apply(sd, level);
+}
+
Index: pjproject/trunk/pjmedia/src/pjmedia/stream.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 228)
+++ pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 229)
@@ -305,4 +305,6 @@
 	    return status;
 	}
+
+	//printf("p"); fflush(stdout);
 
 	/* Encapsulate. */
