Index: pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/conf_switch.c
===================================================================
--- pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/conf_switch.c	(revision 2438)
+++ pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/conf_switch.c	(revision 2444)
@@ -68,4 +68,5 @@
 struct conf_port
 {
+    SLOT_TYPE		 slot;		/**< Array of listeners.	    */
     pj_str_t		 name;		/**< Port name.			    */
     pjmedia_port	*port;		/**< get_frame() and put_frame()    */
@@ -77,7 +78,5 @@
 
     /* Shortcut for port info. */
-    unsigned		 clock_rate;	/**< Port's clock rate.		    */
-    unsigned		 samples_per_frame; /**< Port's samples per frame.  */
-    unsigned		 channel_count;	/**< Port's channel count.	    */
+    pjmedia_port_info	*info;
 
     /* Calculated signal levels: */
@@ -118,8 +117,4 @@
     pj_mutex_t		 *mutex;	/**< Conference mutex.		    */
     struct conf_port	**ports;	/**< Array of ports.		    */
-    unsigned		  clock_rate;	/**< Sampling rate.		    */
-    unsigned		  channel_count;/**< Number of channels (1=mono).   */
-    unsigned		  samples_per_frame;	/**< Samples per frame.	    */
-    unsigned		  bits_per_sample;	/**< Bits per sample.	    */
     pj_uint8_t		  buf[BUFFER_SIZE];	/**< Common buffer.	    */
 };
@@ -146,4 +141,6 @@
     pjmedia_frame *f;
 
+    PJ_ASSERT_RETURN(pool && conf && port && name && p_conf_port, PJ_EINVAL);
+
     /* Create port. */
     conf_port = PJ_POOL_ZALLOC_T(pool, struct conf_port);
@@ -163,15 +160,6 @@
 
     /* Save some port's infos, for convenience. */
-    if (port) {
-	conf_port->port = port;
-	conf_port->clock_rate = port->info.clock_rate;
-	conf_port->samples_per_frame = port->info.samples_per_frame;
-	conf_port->channel_count = port->info.channel_count;
-    } else {
-	conf_port->port = NULL;
-	conf_port->clock_rate = conf->clock_rate;
-	conf_port->samples_per_frame = conf->samples_per_frame;
-	conf_port->channel_count = conf->channel_count;
-    }
+    conf_port->port = port;
+    conf_port->info = &port->info;
 
     /* Init pjmedia_frame structure in the TX buffer. */
@@ -196,5 +184,5 @@
 
 
-    status = create_conf_port(pool, conf, NULL, &name, &conf_port);
+    status = create_conf_port(pool, conf, conf->master_port, &name, &conf_port);
     if (status != PJ_SUCCESS)
 	return status;
@@ -206,4 +194,6 @@
 	pjmedia_snd_stream *strm;
 	pjmedia_snd_stream_info si;
+	pjmedia_port_info *master_port_info = (pjmedia_port_info*)
+					      &conf->master_port->info;
 
 	/*
@@ -212,19 +202,22 @@
 	 */
 	if (conf->options & PJMEDIA_CONF_NO_MIC)  {
-	    status = pjmedia_snd_port_create_player(pool, -1, conf->clock_rate,
-						    conf->channel_count,
-						    conf->samples_per_frame,
-						    conf->bits_per_sample, 
-						    0,	/* options */
-						    &conf->snd_dev_port);
+	    status = pjmedia_snd_port_create_player(
+					pool, -1, 
+					master_port_info->clock_rate,
+					master_port_info->channel_count,
+					master_port_info->samples_per_frame,
+					master_port_info->bits_per_sample, 
+					0,	/* options */
+					&conf->snd_dev_port);
 
 	} else {
-	    status = pjmedia_snd_port_create( pool, -1, -1, conf->clock_rate, 
-					      conf->channel_count, 
-					      conf->samples_per_frame,
-					      conf->bits_per_sample,
-					      0,    /* Options */
-					      &conf->snd_dev_port);
-
+	    status = pjmedia_snd_port_create( 
+					pool, -1, -1, 
+					master_port_info->clock_rate, 
+					master_port_info->channel_count, 
+					master_port_info->samples_per_frame,
+					master_port_info->bits_per_sample,
+					0,    /* Options */
+					&conf->snd_dev_port);
 	}
 
@@ -246,4 +239,5 @@
 
      /* Add the port to the bridge */
+    conf_port->slot = 0;
     conf->ports[0] = conf_port;
     conf->port_cnt++;
@@ -286,9 +280,4 @@
     conf->options = options;
     conf->max_ports = max_ports;
-    conf->clock_rate = clock_rate;
-    conf->channel_count = channel_count;
-    conf->samples_per_frame = samples_per_frame;
-    conf->bits_per_sample = bits_per_sample;
-
     
     /* Create and initialize the master port interface. */
@@ -425,6 +414,5 @@
     conf->ports[0]->name.slen = len;
 
-    if (conf->master_port)
-	conf->master_port->info.name = conf->ports[0]->name;
+    conf->master_port->info.name = conf->ports[0]->name;
 
     return PJ_SUCCESS;
@@ -445,4 +433,5 @@
 
     PJ_ASSERT_RETURN(conf && pool && strm_port, PJ_EINVAL);
+    /*
     PJ_ASSERT_RETURN(conf->clock_rate == strm_port->info.clock_rate, 
 		     PJMEDIA_ENCCLOCKRATE);
@@ -451,8 +440,11 @@
     PJ_ASSERT_RETURN(conf->bits_per_sample == strm_port->info.bits_per_sample,
 		     PJMEDIA_ENCBITS);
+    */
 
     /* Port's samples per frame should be equal to or multiplication of 
      * conference's samples per frame.
      */
+    /*
+    Not sure if this is needed!
     PJ_ASSERT_RETURN((conf->samples_per_frame %
 		     strm_port->info.samples_per_frame==0) ||
@@ -460,4 +452,5 @@
 		     conf->samples_per_frame==0),
 		     PJMEDIA_ENCSAMPLESPFRAME);
+    */
 
     /* If port_name is not specified, use the port's name */
@@ -489,4 +482,5 @@
 
     /* Put the port. */
+    conf_port->slot = index;
     conf->ports[index] = conf_port;
     conf->port_cnt++;
@@ -589,4 +583,14 @@
     dst_port = conf->ports[sink_slot];
 
+    /* Source and sink ptime must be equal or a multiplication factor. */
+    if ((src_port->info->samples_per_frame % 
+	 dst_port->info->samples_per_frame != 0) &&
+        (dst_port->info->samples_per_frame % 
+         src_port->info->samples_per_frame != 0))
+    {
+	pj_mutex_unlock(conf->mutex);
+	return PJMEDIA_ENCSAMPLESPFRAME;
+    }
+    
     /* Check if source and sink has compatible format */
     if (src_slot != 0 && sink_slot != 0 && 
@@ -678,4 +682,7 @@
 	--src_port->listener_cnt;
 	--dst_port->transmitter_cnt;
+	
+	/* Clean up sink TX buffer. */
+	pj_bzero(dst_port->tx_buf, sizeof(pjmedia_frame_ext));
 
 	PJ_LOG(4,(THIS_FILE,
@@ -777,4 +784,7 @@
 	pj_assert(conf->connect_cnt > 0);
 	--conf->connect_cnt;
+
+	/* Clean up TX buffer. */
+	pj_bzero(dst_port->tx_buf, sizeof(pjmedia_frame_ext));
     }
 
@@ -842,10 +852,9 @@
     info->listener_cnt = conf_port->listener_cnt;
     info->listener_slots = conf_port->listener_slots;
-    info->clock_rate = conf_port->clock_rate;
-    info->channel_count = conf_port->channel_count;
-    info->samples_per_frame = conf_port->samples_per_frame;
-    info->bits_per_sample = conf->bits_per_sample;
-    info->format = slot? conf_port->port->info.format : 
-			 conf->master_port->info.format;
+    info->clock_rate = conf_port->info->clock_rate;
+    info->channel_count = conf_port->info->channel_count;
+    info->samples_per_frame = conf_port->info->samples_per_frame;
+    info->bits_per_sample = conf_port->info->bits_per_sample;
+    info->format = conf_port->port->info.format;
 
     return PJ_SUCCESS;
@@ -991,7 +1000,7 @@
 	     * samples per frame.
 	     */
-	    if (f_dst->samples_cnt == cport_dst->samples_per_frame)
+	    if (f_dst->samples_cnt == cport_dst->info->samples_per_frame)
 	    {
-		if (cport_dst->port) {
+		if (cport_dst->slot) {
 		    pjmedia_port_put_frame(cport_dst->port, 
 					   (pjmedia_frame*)f_dst);
@@ -1004,6 +1013,5 @@
 		/* Update TX timestamp. */
 		pj_add_timestamp32(&cport_dst->ts_tx, 
-				   cport_dst->samples_per_frame);
-
+				   cport_dst->info->samples_per_frame);
 	    }
 	}
@@ -1020,7 +1028,9 @@
 	    /* Copy frame to listener's TX buffer. */
 	    nsamples_to_copy = f_end - f_start;
-	    nsamples_req = cport_dst->samples_per_frame - (frm_dst->size>>1);
+	    nsamples_req = cport_dst->info->samples_per_frame - 
+			  (frm_dst->size>>1);
 	    if (nsamples_to_copy > nsamples_req)
 		nsamples_to_copy = nsamples_req;
+
 	    pjmedia_copy_samples((pj_int16_t*)frm_dst->buf + (frm_dst->size>>1),
 				 f_start, 
@@ -1033,7 +1043,7 @@
 	     * samples per frame.
 	     */
-	    if ((frm_dst->size >> 1) == cport_dst->samples_per_frame)
+	    if ((frm_dst->size >> 1) == cport_dst->info->samples_per_frame)
 	    {
-		if (cport_dst->port) {
+		if (cport_dst->slot) {
 		    pjmedia_port_put_frame(cport_dst->port, frm_dst);
 
@@ -1044,5 +1054,5 @@
 		/* Update TX timestamp. */
 		pj_add_timestamp32(&cport_dst->ts_tx, 
-				   cport_dst->samples_per_frame);
+				   cport_dst->info->samples_per_frame);
 	    }
 	}
@@ -1059,10 +1069,10 @@
 	    if (frm_dst->size != 0) {
 		pjmedia_zero_samples((pj_int16_t*)frm_dst->buf,
-				     cport_dst->samples_per_frame - 
+				     cport_dst->info->samples_per_frame - 
 				     (frm_dst->size>>1));
 
 		frm_dst->type = PJMEDIA_FRAME_TYPE_AUDIO;
-		frm_dst->size = cport_dst->samples_per_frame << 1;
-		if (cport_dst->port) {
+		frm_dst->size = cport_dst->info->samples_per_frame << 1;
+		if (cport_dst->slot) {
 		    pjmedia_port_put_frame(cport_dst->port, frm_dst);
 
@@ -1073,5 +1083,5 @@
 		/* Update TX timestamp. */
 		pj_add_timestamp32(&cport_dst->ts_tx, 
-				   cport_dst->samples_per_frame);
+				   cport_dst->info->samples_per_frame);
 	    }
 	} else {
@@ -1081,7 +1091,6 @@
 		frm_dst->type = PJMEDIA_FRAME_TYPE_EXTENDED;
 		pjmedia_frame_ext_append_subframe(f_dst, NULL, 0, (pj_uint16_t)
-						  (cport_dst->samples_per_frame-
-						   f_dst->samples_cnt));
-		if (cport_dst->port) {
+		    (cport_dst->info->samples_per_frame - f_dst->samples_cnt));
+		if (cport_dst->slot) {
 		    pjmedia_port_put_frame(cport_dst->port, frm_dst);
 
@@ -1093,5 +1102,5 @@
 		/* Update TX timestamp. */
 		pj_add_timestamp32(&cport_dst->ts_tx, 
-				   cport_dst->samples_per_frame);
+				   cport_dst->info->samples_per_frame);
 	    }
 	}
@@ -1103,9 +1112,9 @@
 	    frm_dst->type = PJMEDIA_FRAME_TYPE_NONE;
 	    frm_dst->timestamp = cport_dst->ts_tx;
-	    if (cport_dst->port)
+	    if (cport_dst->slot)
 		pjmedia_port_put_frame(cport_dst->port, frm_dst);
 
 	    /* Update TX timestamp. */
-	    pj_add_timestamp32(&cport_dst->ts_tx, cport_dst->samples_per_frame);
+	    pj_add_timestamp32(&cport_dst->ts_tx, cport_dst->info->samples_per_frame);
 	}
     }
@@ -1144,5 +1153,6 @@
 
 	/* Update clock of the port. */
-	pj_add_timestamp32(&cport->ts_clock, conf->samples_per_frame);
+	pj_add_timestamp32(&cport->ts_clock, 
+			   conf->master_port->info.samples_per_frame);
 
 	/* Skip if we're not allowed to receive from this port or 
@@ -1166,5 +1176,5 @@
 	    pj_int32_t level;
 
-	    pj_add_timestamp32(&cport->ts_rx, cport->samples_per_frame);
+	    pj_add_timestamp32(&cport->ts_rx, cport->info->samples_per_frame);
 	    
 	    f->buf = &conf->buf[sizeof(pjmedia_frame)];
@@ -1200,5 +1210,5 @@
 		if (listener->tx_setting == PJMEDIA_PORT_DISABLE) {
 		    pj_add_timestamp32(&listener->ts_tx, 
-				       listener->samples_per_frame);
+				       listener->info->samples_per_frame);
 		    listener->tx_level = 0;
 		    continue;
@@ -1250,5 +1260,5 @@
 
 		    pjmedia_port_put_frame(cport->port, &tmp_f);
-		    pj_add_timestamp32(&cport->ts_tx, cport->samples_per_frame);
+		    pj_add_timestamp32(&cport->ts_tx, cport->info->samples_per_frame);
 		}
 	    }
@@ -1269,5 +1279,5 @@
 	    pj_uint16_t samples_per_subframe;
 	    
-	    if (f_src_->samples_cnt < this_cport->samples_per_frame) {
+	    if (f_src_->samples_cnt < this_cport->info->samples_per_frame) {
 		pj_bzero(this_cport->tx_buf, sizeof(pjmedia_frame_ext));
 		frame->type = PJMEDIA_FRAME_TYPE_NONE;
@@ -1281,5 +1291,5 @@
 
 
-	    while (f_dst->samples_cnt < this_cport->samples_per_frame) {
+	    while (f_dst->samples_cnt < this_cport->info->samples_per_frame) {
 		sf = pjmedia_frame_ext_get_subframe(f_src_, i++);
 		pj_assert(sf);
@@ -1292,5 +1302,5 @@
 
 	} else if (f_src->type == PJMEDIA_FRAME_TYPE_AUDIO) {
-	    if ((f_src->size>>1) < this_cport->samples_per_frame) {
+	    if ((f_src->size>>1) < this_cport->info->samples_per_frame) {
 		pj_bzero(this_cport->tx_buf, sizeof(pjmedia_frame_ext));
 		frame->type = PJMEDIA_FRAME_TYPE_NONE;
@@ -1300,6 +1310,6 @@
 	    pjmedia_copy_samples((pj_int16_t*)frame->buf, 
 				 (pj_int16_t*)f_src->buf, 
-				 this_cport->samples_per_frame);
-	    frame->size = this_cport->samples_per_frame << 1;
+				 this_cport->info->samples_per_frame);
+	    frame->size = this_cport->info->samples_per_frame << 1;
 
 	    /* Shift left TX buffer. */
@@ -1308,5 +1318,5 @@
 		pjmedia_move_samples((pj_int16_t*)f_src->buf,
 				     (pj_int16_t*)f_src->buf + 
-				     this_cport->samples_per_frame,
+				     this_cport->info->samples_per_frame,
 				     f_src->size >> 1);
 	} else { /* PJMEDIA_FRAME_TYPE_NONE */
@@ -1334,5 +1344,5 @@
     pj_int32_t level;
 
-    pj_add_timestamp32(&cport->ts_rx, cport->samples_per_frame);
+    pj_add_timestamp32(&cport->ts_rx, cport->info->samples_per_frame);
     
     /* Skip if this port is muted/disabled. */
@@ -1373,5 +1383,5 @@
 	if (listener->tx_setting == PJMEDIA_PORT_DISABLE) {
 	    pj_add_timestamp32(&listener->ts_tx, 
-			       listener->samples_per_frame);
+			       listener->info->samples_per_frame);
 	    listener->tx_level = 0;
 	    continue;
@@ -1381,5 +1391,5 @@
 	if (listener == cport) {
 	    pj_add_timestamp32(&listener->ts_tx, 
-			       listener->samples_per_frame);
+			       listener->info->samples_per_frame);
 	    listener->tx_level = 0;
 	    continue;
