* #36737: switch back to svn repo, remove assert in sip_transaction.c
diff --git a/jni/pjproject-android/.svn/pristine/f1/f1083269fc8b86c30e001360c18772aca40525cd.svn-base b/jni/pjproject-android/.svn/pristine/f1/f1083269fc8b86c30e001360c18772aca40525cd.svn-base
new file mode 100644
index 0000000..2ef6538
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f1/f1083269fc8b86c30e001360c18772aca40525cd.svn-base
@@ -0,0 +1,2098 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pjmedia/conference.h>
+#include <pjmedia/alaw_ulaw.h>
+#include <pjmedia/delaybuf.h>
+#include <pjmedia/errno.h>
+#include <pjmedia/port.h>
+#include <pjmedia/resample.h>
+#include <pjmedia/silencedet.h>
+#include <pjmedia/sound_port.h>
+#include <pjmedia/stereo.h>
+#include <pj/array.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+
+#if !defined(PJMEDIA_CONF_USE_SWITCH_BOARD) || PJMEDIA_CONF_USE_SWITCH_BOARD==0
+
+/* CONF_DEBUG enables detailed operation of the conference bridge.
+ * Beware that it prints large amounts of logs (several lines per frame).
+ */
+//#define CONF_DEBUG
+#ifdef CONF_DEBUG
+#   include <stdio.h>
+#   define TRACE_(x)   PJ_LOG(5,x)
+#else
+#   define TRACE_(x)
+#endif
+
+
+/* REC_FILE macro enables recording of the samples written to the sound
+ * device. The file contains RAW PCM data with no header, and has the
+ * same settings (clock rate etc) as the conference bridge.
+ * This should only be enabled when debugging audio quality *only*.
+ */
+//#define REC_FILE    "confrec.pcm"
+#ifdef REC_FILE
+static FILE *fhnd_rec;
+#endif
+
+
+#define THIS_FILE	"conference.c"
+
+#define RX_BUF_COUNT	    PJMEDIA_SOUND_BUFFER_COUNT
+
+#define BYTES_PER_SAMPLE    2
+
+#define SIGNATURE	    PJMEDIA_CONF_BRIDGE_SIGNATURE
+#define SIGNATURE_PORT	    PJMEDIA_SIG_PORT_CONF_PASV
+/* Normal level is hardcodec to 128 in all over places */
+#define NORMAL_LEVEL	    128
+#define SLOT_TYPE	    unsigned
+#define INVALID_SLOT	    ((SLOT_TYPE)-1)
+
+
+/* These are settings to control the adaptivity of changes in the
+ * signal level of the ports, so that sudden change in signal level
+ * in the port does not cause misaligned signal (which causes noise).
+ */
+#define ATTACK_A    (conf->clock_rate / conf->samples_per_frame)
+#define ATTACK_B    1
+#define DECAY_A	    0
+#define DECAY_B	    1
+
+#define SIMPLE_AGC(last, target) \
+    if (target >= last) \
+	target = (ATTACK_A*(last+1)+ATTACK_B*target)/(ATTACK_A+ATTACK_B); \
+    else \
+	target = (DECAY_A*last+DECAY_B*target)/(DECAY_A+DECAY_B)
+
+#define MAX_LEVEL   (32767)
+#define MIN_LEVEL   (-32768)
+
+#define IS_OVERFLOW(s) ((s > MAX_LEVEL) || (s < MIN_LEVEL))
+
+
+/*
+ * DON'T GET CONFUSED WITH TX/RX!!
+ *
+ * TX and RX directions are always viewed from the conference bridge's point
+ * of view, and NOT from the port's point of view. So TX means the bridge
+ * is transmitting to the port, RX means the bridge is receiving from the
+ * port.
+ */
+
+
+/**
+ * This is a port connected to conference bridge.
+ */
+struct conf_port
+{
+    pj_str_t		 name;		/**< Port name.			    */
+    pjmedia_port	*port;		/**< get_frame() and put_frame()    */
+    pjmedia_port_op	 rx_setting;	/**< Can we receive from this port  */
+    pjmedia_port_op	 tx_setting;	/**< Can we transmit to this port   */
+    unsigned		 listener_cnt;	/**< Number of listeners.	    */
+    SLOT_TYPE		*listener_slots;/**< Array of listeners.	    */
+    unsigned		 transmitter_cnt;/**<Number of transmitters.	    */
+
+    /* 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.	    */
+
+    /* Calculated signal levels: */
+    unsigned		 tx_level;	/**< Last tx level to this port.    */
+    unsigned		 rx_level;	/**< Last rx level from this port.  */
+
+    /* The normalized signal level adjustment.
+     * A value of 128 (NORMAL_LEVEL) means there's no adjustment.
+     */
+    unsigned		 tx_adj_level;	/**< Adjustment for TX.		    */
+    unsigned		 rx_adj_level;	/**< Adjustment for RX.		    */
+
+    /* Resample, for converting clock rate, if they're different. */
+    pjmedia_resample	*rx_resample;
+    pjmedia_resample	*tx_resample;
+
+    /* RX buffer is temporary buffer to be used when there is mismatch
+     * between port's sample rate or ptime with conference's sample rate
+     * or ptime. The buffer is used for sampling rate conversion AND/OR to
+     * buffer the samples until there are enough samples to fulfill a 
+     * complete frame to be processed by the bridge.
+     *
+     * When both sample rate AND ptime of the port match the conference 
+     * settings, this buffer will not be created.
+     * 
+     * This buffer contains samples at port's clock rate.
+     * The size of this buffer is the sum between port's samples per frame
+     * and bridge's samples per frame.
+     */
+    pj_int16_t		*rx_buf;	/**< The RX buffer.		    */
+    unsigned		 rx_buf_cap;	/**< Max size, in samples	    */
+    unsigned		 rx_buf_count;	/**< # of samples in the buf.	    */
+
+    /* Mix buf is a temporary buffer used to mix all signal received
+     * by this port from all other ports. The mixed signal will be 
+     * automatically adjusted to the appropriate level whenever
+     * there is possibility of clipping.
+     *
+     * This buffer contains samples at bridge's clock rate.
+     * The size of this buffer is equal to samples per frame of the bridge.
+     */
+
+    int			 mix_adj;	/**< Adjustment level for mix_buf.  */
+    int			 last_mix_adj;	/**< Last adjustment level.	    */
+    pj_int32_t		*mix_buf;	/**< Total sum of signal.	    */
+
+    /* Tx buffer is a temporary buffer to be used when there's mismatch 
+     * between port's clock rate or ptime with conference's sample rate
+     * or ptime. This buffer is used as the source of the sampling rate
+     * conversion AND/OR to buffer the samples until there are enough
+     * samples to fulfill a complete frame to be transmitted to the port.
+     *
+     * When both sample rate and ptime of the port match the bridge's 
+     * settings, this buffer will not be created.
+     * 
+     * This buffer contains samples at port's clock rate.
+     * The size of this buffer is the sum between port's samples per frame
+     * and bridge's samples per frame.
+     */
+    pj_int16_t		*tx_buf;	/**< Tx buffer.			    */
+    unsigned		 tx_buf_cap;	/**< Max size, in samples.	    */
+    unsigned		 tx_buf_count;	/**< # of samples in the buffer.    */
+
+    /* When the port is not receiving signal from any other ports (e.g. when
+     * no other ports is transmitting to this port), the bridge periodically
+     * transmit NULL frame to the port to keep the port "alive" (for example,
+     * a stream port needs this heart-beat to periodically transmit silence
+     * frame to keep NAT binding alive).
+     *
+     * This NULL frame should be sent to the port at the port's ptime rate.
+     * So if the port's ptime is greater than the bridge's ptime, the bridge
+     * needs to delay the NULL frame until it's the right time to do so.
+     *
+     * This variable keeps track of how many pending NULL samples are being
+     * "held" for this port. Once this value reaches samples_per_frame
+     * value of the port, a NULL frame is sent. The samples value on this
+     * variable is clocked at the port's clock rate.
+     */
+    unsigned		 tx_heart_beat;
+
+    /* Delay buffer is a special buffer for sound device port (port 0, master
+     * port) and other passive ports (sound device port is also passive port).
+     *
+     * We need the delay buffer because we can not expect the mic and speaker 
+     * thread to run equally after one another. In most systems, each thread 
+     * will run multiple times before the other thread gains execution time. 
+     * For example, in my system, mic thread is called three times, then 
+     * speaker thread is called three times, and so on. This we call burst.
+     *
+     * There is also possibility of drift, unbalanced rate between put_frame
+     * and get_frame operation, in passive ports. If drift happens, snd_buf
+     * needs to be expanded or shrinked. 
+     *
+     * Burst and drift are handled by delay buffer.
+     */
+    pjmedia_delay_buf	*delay_buf;
+};
+
+
+/*
+ * Conference bridge.
+ */
+struct pjmedia_conf
+{
+    unsigned		  options;	/**< Bitmask options.		    */
+    unsigned		  max_ports;	/**< Maximum ports.		    */
+    unsigned		  port_cnt;	/**< Current number of ports.	    */
+    unsigned		  connect_cnt;	/**< Total number of connections    */
+    pjmedia_snd_port	 *snd_dev_port;	/**< Sound device port.		    */
+    pjmedia_port	 *master_port;	/**< Port zero's port.		    */
+    char		  master_name_buf[80]; /**< Port0 name buffer.	    */
+    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.	    */
+};
+
+
+/* Prototypes */
+static pj_status_t put_frame(pjmedia_port *this_port, 
+			     pjmedia_frame *frame);
+static pj_status_t get_frame(pjmedia_port *this_port, 
+			     pjmedia_frame *frame);
+static pj_status_t get_frame_pasv(pjmedia_port *this_port, 
+				  pjmedia_frame *frame);
+static pj_status_t destroy_port(pjmedia_port *this_port);
+static pj_status_t destroy_port_pasv(pjmedia_port *this_port);
+
+
+/*
+ * Create port.
+ */
+static pj_status_t create_conf_port( pj_pool_t *pool,
+				     pjmedia_conf *conf,
+				     pjmedia_port *port,
+				     const pj_str_t *name,
+				     struct conf_port **p_conf_port)
+{
+    struct conf_port *conf_port;
+    pj_status_t status;
+
+    /* Create port. */
+    conf_port = PJ_POOL_ZALLOC_T(pool, struct conf_port);
+    PJ_ASSERT_RETURN(conf_port, PJ_ENOMEM);
+
+    /* Set name */
+    pj_strdup_with_null(pool, &conf_port->name, name);
+
+    /* Default has tx and rx enabled. */
+    conf_port->rx_setting = PJMEDIA_PORT_ENABLE;
+    conf_port->tx_setting = PJMEDIA_PORT_ENABLE;
+
+    /* Default level adjustment is 128 (which means no adjustment) */
+    conf_port->tx_adj_level = NORMAL_LEVEL;
+    conf_port->rx_adj_level = NORMAL_LEVEL;
+
+    /* Create transmit flag array */
+    conf_port->listener_slots = (SLOT_TYPE*)
+				pj_pool_zalloc(pool, 
+					  conf->max_ports * sizeof(SLOT_TYPE));
+    PJ_ASSERT_RETURN(conf_port->listener_slots, PJ_ENOMEM);
+
+    /* Save some port's infos, for convenience. */
+    if (port) {
+	pjmedia_audio_format_detail *afd;
+
+	afd = pjmedia_format_get_audio_format_detail(&port->info.fmt, 1);
+	conf_port->port = port;
+	conf_port->clock_rate = afd->clock_rate;
+	conf_port->samples_per_frame = PJMEDIA_AFD_SPF(afd);
+	conf_port->channel_count = afd->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;
+    }
+
+    /* If port's clock rate is different than conference's clock rate,
+     * create a resample sessions.
+     */
+    if (conf_port->clock_rate != conf->clock_rate) {
+
+	pj_bool_t high_quality;
+	pj_bool_t large_filter;
+
+	high_quality = ((conf->options & PJMEDIA_CONF_USE_LINEAR)==0);
+	large_filter = ((conf->options & PJMEDIA_CONF_SMALL_FILTER)==0);
+
+	/* Create resample for rx buffer. */
+	status = pjmedia_resample_create( pool, 
+					  high_quality,
+					  large_filter,
+					  conf->channel_count,
+					  conf_port->clock_rate,/* Rate in */
+					  conf->clock_rate, /* Rate out */
+					  conf->samples_per_frame * 
+					    conf_port->clock_rate /
+					    conf->clock_rate,
+					  &conf_port->rx_resample);
+	if (status != PJ_SUCCESS)
+	    return status;
+
+
+	/* Create resample for tx buffer. */
+	status = pjmedia_resample_create(pool,
+					 high_quality,
+					 large_filter,
+					 conf->channel_count,
+					 conf->clock_rate,  /* Rate in */
+					 conf_port->clock_rate, /* Rate out */
+					 conf->samples_per_frame,
+					 &conf_port->tx_resample);
+	if (status != PJ_SUCCESS)
+	    return status;
+    }
+
+    /*
+     * Initialize rx and tx buffer, only when port's samples per frame or 
+     * port's clock rate or channel number is different then the conference
+     * bridge settings.
+     */
+    if (conf_port->clock_rate != conf->clock_rate ||
+	conf_port->channel_count != conf->channel_count ||
+	conf_port->samples_per_frame != conf->samples_per_frame)
+    {
+	unsigned port_ptime, conf_ptime, buff_ptime;
+
+	port_ptime = conf_port->samples_per_frame / conf_port->channel_count *
+	    1000 / conf_port->clock_rate;
+	conf_ptime = conf->samples_per_frame / conf->channel_count *
+	    1000 / conf->clock_rate;
+
+	/* Calculate the size (in ptime) for the port buffer according to
+	 * this formula:
+	 *   - if either ptime is an exact multiple of the other, then use
+	 *     the larger ptime (e.g. 20ms and 40ms, use 40ms).
+	 *   - if not, then the ptime is sum of both ptimes (e.g. 20ms
+	 *     and 30ms, use 50ms)
+	 */
+	if (port_ptime > conf_ptime) {
+	    buff_ptime = port_ptime;
+	    if (port_ptime % conf_ptime)
+		buff_ptime += conf_ptime;
+	} else {
+	    buff_ptime = conf_ptime;
+	    if (conf_ptime % port_ptime)
+		buff_ptime += port_ptime;
+	}
+
+	/* Create RX buffer. */
+	//conf_port->rx_buf_cap = (unsigned)(conf_port->samples_per_frame +
+	//				   conf->samples_per_frame * 
+	//				   conf_port->clock_rate * 1.0 /
+	//				   conf->clock_rate + 0.5);
+	conf_port->rx_buf_cap = conf_port->clock_rate * buff_ptime / 1000;
+	if (conf_port->channel_count > conf->channel_count)
+	    conf_port->rx_buf_cap *= conf_port->channel_count;
+	else
+	    conf_port->rx_buf_cap *= conf->channel_count;
+
+	conf_port->rx_buf_count = 0;
+	conf_port->rx_buf = (pj_int16_t*)
+			    pj_pool_alloc(pool, conf_port->rx_buf_cap *
+						sizeof(conf_port->rx_buf[0]));
+	PJ_ASSERT_RETURN(conf_port->rx_buf, PJ_ENOMEM);
+
+	/* Create TX buffer. */
+	conf_port->tx_buf_cap = conf_port->rx_buf_cap;
+	conf_port->tx_buf_count = 0;
+	conf_port->tx_buf = (pj_int16_t*)
+			    pj_pool_alloc(pool, conf_port->tx_buf_cap *
+						sizeof(conf_port->tx_buf[0]));
+	PJ_ASSERT_RETURN(conf_port->tx_buf, PJ_ENOMEM);
+    }
+
+
+    /* Create mix buffer. */
+    conf_port->mix_buf = (pj_int32_t*)
+			 pj_pool_zalloc(pool, conf->samples_per_frame *
+					      sizeof(conf_port->mix_buf[0]));
+    PJ_ASSERT_RETURN(conf_port->mix_buf, PJ_ENOMEM);
+    conf_port->last_mix_adj = NORMAL_LEVEL;
+
+
+    /* Done */
+    *p_conf_port = conf_port;
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Add passive port.
+ */
+static pj_status_t create_pasv_port( pjmedia_conf *conf,
+				     pj_pool_t *pool,
+				     const pj_str_t *name,
+				     pjmedia_port *port,
+				     struct conf_port **p_conf_port)
+{
+    struct conf_port *conf_port;
+    pj_status_t status;
+    unsigned ptime;
+
+    /* Create port */
+    status = create_conf_port(pool, conf, port, name, &conf_port);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    /* Passive port has delay buf. */
+    ptime = conf->samples_per_frame * 1000 / conf->clock_rate / 
+	    conf->channel_count;
+    status = pjmedia_delay_buf_create(pool, name->ptr, 
+				      conf->clock_rate,
+				      conf->samples_per_frame,
+				      conf->channel_count,
+				      RX_BUF_COUNT * ptime, /* max delay */
+				      0, /* options */
+				      &conf_port->delay_buf);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    *p_conf_port = conf_port;
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Create port zero for the sound device.
+ */
+static pj_status_t create_sound_port( pj_pool_t *pool,
+				      pjmedia_conf *conf )
+{
+    struct conf_port *conf_port;
+    pj_str_t name = { "Master/sound", 12 };
+    pj_status_t status;
+
+
+    status = create_pasv_port(conf, pool, &name, NULL, &conf_port);
+    if (status != PJ_SUCCESS)
+	return status;
+
+
+    /* Create sound device port: */
+
+    if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) {
+	pjmedia_aud_stream *strm;
+	pjmedia_aud_param param;
+
+	/*
+	 * If capture is disabled then create player only port.
+	 * Otherwise create bidirectional sound device port.
+	 */
+	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);
+
+	} 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);
+
+	}
+
+	if (status != PJ_SUCCESS)
+	    return status;
+
+	strm = pjmedia_snd_port_get_snd_stream(conf->snd_dev_port);
+	status = pjmedia_aud_stream_get_param(strm, &param);
+	if (status == PJ_SUCCESS) {
+	    pjmedia_aud_dev_info snd_dev_info;
+	    if (conf->options & PJMEDIA_CONF_NO_MIC)
+		pjmedia_aud_dev_get_info(param.play_id, &snd_dev_info);
+	    else
+		pjmedia_aud_dev_get_info(param.rec_id, &snd_dev_info);
+	    pj_strdup2_with_null(pool, &conf_port->name, snd_dev_info.name);
+	}
+
+	PJ_LOG(5,(THIS_FILE, "Sound device successfully created for port 0"));
+    }
+
+
+     /* Add the port to the bridge */
+    conf->ports[0] = conf_port;
+    conf->port_cnt++;
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Create conference bridge.
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_create( pj_pool_t *pool,
+					 unsigned max_ports,
+					 unsigned clock_rate,
+					 unsigned channel_count,
+					 unsigned samples_per_frame,
+					 unsigned bits_per_sample,
+					 unsigned options,
+					 pjmedia_conf **p_conf )
+{
+    pjmedia_conf *conf;
+    const pj_str_t name = { "Conf", 4 };
+    pj_status_t status;
+
+    /* Can only accept 16bits per sample, for now.. */
+    PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);
+
+    PJ_LOG(5,(THIS_FILE, "Creating conference bridge with %d ports",
+	      max_ports));
+
+    /* Create and init conf structure. */
+    conf = PJ_POOL_ZALLOC_T(pool, pjmedia_conf);
+    PJ_ASSERT_RETURN(conf, PJ_ENOMEM);
+
+    conf->ports = (struct conf_port**) 
+		  pj_pool_zalloc(pool, max_ports*sizeof(void*));
+    PJ_ASSERT_RETURN(conf->ports, PJ_ENOMEM);
+
+    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. */
+    conf->master_port = PJ_POOL_ZALLOC_T(pool, pjmedia_port);
+    PJ_ASSERT_RETURN(conf->master_port, PJ_ENOMEM);
+    
+    pjmedia_port_info_init(&conf->master_port->info, &name, SIGNATURE,
+			   clock_rate, channel_count, bits_per_sample,
+			   samples_per_frame);
+
+    conf->master_port->port_data.pdata = conf;
+    conf->master_port->port_data.ldata = 0;
+
+    conf->master_port->get_frame = &get_frame;
+    conf->master_port->put_frame = &put_frame;
+    conf->master_port->on_destroy = &destroy_port;
+
+
+    /* Create port zero for sound device. */
+    status = create_sound_port(pool, conf);
+    if (status != PJ_SUCCESS) {
+	pjmedia_conf_destroy(conf);
+	return status;
+    }
+
+    /* Create mutex. */
+    status = pj_mutex_create_recursive(pool, "conf", &conf->mutex);
+    if (status != PJ_SUCCESS) {
+	pjmedia_conf_destroy(conf);
+	return status;
+    }
+
+    /* If sound device was created, connect sound device to the
+     * master port.
+     */
+    if (conf->snd_dev_port) {
+	status = pjmedia_snd_port_connect( conf->snd_dev_port, 
+					   conf->master_port );
+	if (status != PJ_SUCCESS) {
+	    pjmedia_conf_destroy(conf);
+	    return status;
+	}
+    }
+
+
+    /* Done */
+
+    *p_conf = conf;
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Pause sound device.
+ */
+static pj_status_t pause_sound( pjmedia_conf *conf )
+{
+    /* Do nothing. */
+    PJ_UNUSED_ARG(conf);
+    return PJ_SUCCESS;
+}
+
+/*
+ * Resume sound device.
+ */
+static pj_status_t resume_sound( pjmedia_conf *conf )
+{
+    /* Do nothing. */
+    PJ_UNUSED_ARG(conf);
+    return PJ_SUCCESS;
+}
+
+
+/**
+ * Destroy conference bridge.
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_destroy( pjmedia_conf *conf )
+{
+    unsigned i, ci;
+
+    PJ_ASSERT_RETURN(conf != NULL, PJ_EINVAL);
+
+    /* Destroy sound device port. */
+    if (conf->snd_dev_port) {
+	pjmedia_snd_port_destroy(conf->snd_dev_port);
+	conf->snd_dev_port = NULL;
+    }
+
+    /* Destroy delay buf of all (passive) ports. */
+    for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) {
+	struct conf_port *cport;
+
+	cport = conf->ports[i];
+	if (!cport)
+	    continue;
+	
+	++ci;
+	if (cport->delay_buf) {
+	    pjmedia_delay_buf_destroy(cport->delay_buf);
+	    cport->delay_buf = NULL;
+	}
+    }
+
+    /* Destroy mutex */
+    if (conf->mutex)
+	pj_mutex_destroy(conf->mutex);
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Destroy the master port (will destroy the conference)
+ */
+static pj_status_t destroy_port(pjmedia_port *this_port)
+{
+    pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata;
+    return pjmedia_conf_destroy(conf);
+}
+
+static pj_status_t destroy_port_pasv(pjmedia_port *this_port) {
+    pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata;
+    struct conf_port *port = conf->ports[this_port->port_data.ldata];
+    pj_status_t status;
+
+    status = pjmedia_delay_buf_destroy(port->delay_buf);
+    if (status == PJ_SUCCESS)
+	port->delay_buf = NULL;
+
+    return status;
+}
+
+/*
+ * Get port zero interface.
+ */
+PJ_DEF(pjmedia_port*) pjmedia_conf_get_master_port(pjmedia_conf *conf)
+{
+    /* Sanity check. */
+    PJ_ASSERT_RETURN(conf != NULL, NULL);
+
+    /* Can only return port interface when PJMEDIA_CONF_NO_DEVICE was
+     * present in the option.
+     */
+    PJ_ASSERT_RETURN((conf->options & PJMEDIA_CONF_NO_DEVICE) != 0, NULL);
+    
+    return conf->master_port;
+}
+
+
+/*
+ * Set master port name.
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_set_port0_name(pjmedia_conf *conf,
+						const pj_str_t *name)
+{
+    pj_size_t len;
+
+    /* Sanity check. */
+    PJ_ASSERT_RETURN(conf != NULL && name != NULL, PJ_EINVAL);
+
+    len = name->slen;
+    if (len > sizeof(conf->master_name_buf))
+	len = sizeof(conf->master_name_buf);
+    
+    if (len > 0) pj_memcpy(conf->master_name_buf, name->ptr, len);
+
+    conf->ports[0]->name.ptr = conf->master_name_buf;
+    conf->ports[0]->name.slen = len;
+
+    if (conf->master_port)
+	conf->master_port->info.name = conf->ports[0]->name;
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Add stream port to the conference bridge.
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_add_port( pjmedia_conf *conf,
+					   pj_pool_t *pool,
+					   pjmedia_port *strm_port,
+					   const pj_str_t *port_name,
+					   unsigned *p_port )
+{
+    struct conf_port *conf_port;
+    unsigned index;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(conf && pool && strm_port, PJ_EINVAL);
+
+    /* If port_name is not specified, use the port's name */
+    if (!port_name)
+	port_name = &strm_port->info.name;
+
+    /* For this version of PJMEDIA, channel(s) number MUST be:
+     * - same between port & conference bridge.
+     * - monochannel on port or conference bridge.
+     */
+    if (PJMEDIA_PIA_CCNT(&strm_port->info) != conf->channel_count &&
+	(PJMEDIA_PIA_CCNT(&strm_port->info) != 1 &&
+	 conf->channel_count != 1))
+    {
+	pj_assert(!"Number of channels mismatch");
+	return PJMEDIA_ENCCHANNEL;
+    }
+
+    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;
+    }
+
+    /* Find empty port in the conference bridge. */
+    for (index=0; index < conf->max_ports; ++index) {
+	if (conf->ports[index] == NULL)
+	    break;
+    }
+
+    pj_assert(index != conf->max_ports);
+
+    /* Create conf port structure. */
+    status = create_conf_port(pool, conf, strm_port, port_name, &conf_port);
+    if (status != PJ_SUCCESS) {
+	pj_mutex_unlock(conf->mutex);
+	return status;
+    }
+
+    /* Put the port. */
+    conf->ports[index] = conf_port;
+    conf->port_cnt++;
+
+    /* Done. */
+    if (p_port) {
+	*p_port = index;
+    }
+
+    pj_mutex_unlock(conf->mutex);
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Add passive port.
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_add_passive_port( pjmedia_conf *conf,
+						   pj_pool_t *pool,
+						   const pj_str_t *name,
+						   unsigned clock_rate,
+						   unsigned channel_count,
+						   unsigned samples_per_frame,
+						   unsigned bits_per_sample,
+						   unsigned options,
+						   unsigned *p_slot,
+						   pjmedia_port **p_port )
+{
+    struct conf_port *conf_port;
+    pjmedia_port *port;
+    unsigned index;
+    pj_str_t tmp;
+    pj_status_t status;
+
+    PJ_LOG(1, (THIS_FILE, "This API has been deprecated since 1.3 and will "
+			  "be removed in the future release!"));
+
+    PJ_ASSERT_RETURN(conf && pool, PJ_EINVAL);
+
+    /* For this version of PJMEDIA, channel(s) number MUST be:
+     * - same between port & conference bridge.
+     * - monochannel on port or conference bridge.
+     */
+    if (channel_count != conf->channel_count && 
+	(channel_count != 1 && conf->channel_count != 1)) 
+    {
+	pj_assert(!"Number of channels mismatch");
+	return PJMEDIA_ENCCHANNEL;
+    }
+
+    /* For this version, options must be zero */
+    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);
+    PJ_UNUSED_ARG(options);
+
+    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;
+    }
+
+    /* Find empty port in the conference bridge. */
+    for (index=0; index < conf->max_ports; ++index) {
+	if (conf->ports[index] == NULL)
+	    break;
+    }
+
+    pj_assert(index != conf->max_ports);
+
+    if (name == NULL) {
+	name = &tmp;
+
+	tmp.ptr = (char*) pj_pool_alloc(pool, 32);
+	tmp.slen = pj_ansi_snprintf(tmp.ptr, 32, "ConfPort#%d", index);
+    }
+
+    /* Create and initialize the media port structure. */
+    port = PJ_POOL_ZALLOC_T(pool, pjmedia_port);
+    PJ_ASSERT_RETURN(port, PJ_ENOMEM);
+    
+    pjmedia_port_info_init(&port->info, name, SIGNATURE_PORT,
+			   clock_rate, channel_count, bits_per_sample,
+			   samples_per_frame);
+
+    port->port_data.pdata = conf;
+    port->port_data.ldata = index;
+
+    port->get_frame = &get_frame_pasv;
+    port->put_frame = &put_frame;
+    port->on_destroy = &destroy_port_pasv;
+
+    
+    /* Create conf port structure. */
+    status = create_pasv_port(conf, pool, name, port, &conf_port);
+    if (status != PJ_SUCCESS) {
+	pj_mutex_unlock(conf->mutex);
+	return status;
+    }
+
+
+    /* Put the port. */
+    conf->ports[index] = conf_port;
+    conf->port_cnt++;
+
+    /* Done. */
+    if (p_slot)
+	*p_slot = index;
+    if (p_port)
+	*p_port = port;
+
+    pj_mutex_unlock(conf->mutex);
+
+    return PJ_SUCCESS;
+}
+
+
+
+/*
+ * Change TX and RX settings for the port.
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_configure_port( pjmedia_conf *conf,
+						  unsigned slot,
+						  pjmedia_port_op tx,
+						  pjmedia_port_op rx)
+{
+    struct conf_port *conf_port;
+
+    /* Check arguments */
+    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
+
+    pj_mutex_lock(conf->mutex);
+
+    /* Port must be valid. */
+    conf_port = conf->ports[slot];
+    if (conf_port == NULL) {
+	pj_mutex_unlock(conf->mutex);
+	return PJ_EINVAL;
+    }
+
+    conf_port = conf->ports[slot];
+
+    if (tx != PJMEDIA_PORT_NO_CHANGE)
+	conf_port->tx_setting = tx;
+
+    if (rx != PJMEDIA_PORT_NO_CHANGE)
+	conf_port->rx_setting = rx;
+
+    pj_mutex_unlock(conf->mutex);
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Connect port.
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf,
+					       unsigned src_slot,
+					       unsigned sink_slot,
+					       int level )
+{
+    struct conf_port *src_port, *dst_port;
+    pj_bool_t start_sound = PJ_FALSE;
+    unsigned i;
+
+    /* Check arguments */
+    PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports && 
+		     sink_slot<conf->max_ports, PJ_EINVAL);
+
+    /* For now, level MUST be zero. */
+    PJ_ASSERT_RETURN(level == 0, PJ_EINVAL);
+
+    pj_mutex_lock(conf->mutex);
+
+    /* Ports must be valid. */
+    src_port = conf->ports[src_slot];
+    dst_port = conf->ports[sink_slot];
+    if (!src_port || !dst_port) {
+	pj_mutex_unlock(conf->mutex);
+	return PJ_EINVAL;
+    }
+
+    /* Check if connection has been made */
+    for (i=0; i<src_port->listener_cnt; ++i) {
+	if (src_port->listener_slots[i] == sink_slot)
+	    break;
+    }
+
+    if (i == src_port->listener_cnt) {
+	src_port->listener_slots[src_port->listener_cnt] = sink_slot;
+	++conf->connect_cnt;
+	++src_port->listener_cnt;
+	++dst_port->transmitter_cnt;
+
+	if (conf->connect_cnt == 1)
+	    start_sound = 1;
+
+	PJ_LOG(4,(THIS_FILE,"Port %d (%.*s) transmitting to port %d (%.*s)",
+		  src_slot,
+		  (int)src_port->name.slen,
+		  src_port->name.ptr,
+		  sink_slot,
+		  (int)dst_port->name.slen,
+		  dst_port->name.ptr));
+    }
+
+    pj_mutex_unlock(conf->mutex);
+
+    /* Sound device must be started without mutex, otherwise the
+     * sound thread will deadlock (?)
+     */
+    if (start_sound)
+	resume_sound(conf);
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Disconnect port
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf,
+						  unsigned src_slot,
+						  unsigned sink_slot )
+{
+    struct conf_port *src_port, *dst_port;
+    unsigned i;
+
+    /* Check arguments */
+    PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports && 
+		     sink_slot<conf->max_ports, PJ_EINVAL);
+
+    pj_mutex_lock(conf->mutex);
+
+    /* Ports must be valid. */
+    src_port = conf->ports[src_slot];
+    dst_port = conf->ports[sink_slot];
+    if (!src_port || !dst_port) {
+	pj_mutex_unlock(conf->mutex);
+	return PJ_EINVAL;
+    }
+
+    /* Check if connection has been made */
+    for (i=0; i<src_port->listener_cnt; ++i) {
+	if (src_port->listener_slots[i] == sink_slot)
+	    break;
+    }
+
+    if (i != src_port->listener_cnt) {
+	pj_assert(src_port->listener_cnt > 0 && 
+		  src_port->listener_cnt < conf->max_ports);
+	pj_assert(dst_port->transmitter_cnt > 0 && 
+		  dst_port->transmitter_cnt < conf->max_ports);
+	pj_array_erase(src_port->listener_slots, sizeof(SLOT_TYPE), 
+		       src_port->listener_cnt, i);
+	--conf->connect_cnt;
+	--src_port->listener_cnt;
+	--dst_port->transmitter_cnt;
+
+	PJ_LOG(4,(THIS_FILE,
+		  "Port %d (%.*s) stop transmitting to port %d (%.*s)",
+		  src_slot,
+		  (int)src_port->name.slen,
+		  src_port->name.ptr,
+		  sink_slot,
+		  (int)dst_port->name.slen,
+		  dst_port->name.ptr));
+
+	/* if source port is passive port and has no listener, reset delaybuf */
+	if (src_port->delay_buf && src_port->listener_cnt == 0)
+	    pjmedia_delay_buf_reset(src_port->delay_buf);
+    }
+
+    pj_mutex_unlock(conf->mutex);
+
+    if (conf->connect_cnt == 0) {
+	pause_sound(conf);
+    }
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Get number of ports currently registered to the conference bridge.
+ */
+PJ_DEF(unsigned) pjmedia_conf_get_port_count(pjmedia_conf *conf)
+{
+    return conf->port_cnt;
+}
+
+/*
+ * Get total number of ports connections currently set up in the bridge.
+ */
+PJ_DEF(unsigned) pjmedia_conf_get_connect_count(pjmedia_conf *conf)
+{
+    return conf->connect_cnt;
+}
+
+
+/*
+ * Remove the specified port.
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_remove_port( pjmedia_conf *conf,
+					      unsigned port )
+{
+    struct conf_port *conf_port;
+    unsigned i;
+
+    /* Check arguments */
+    PJ_ASSERT_RETURN(conf && port < conf->max_ports, PJ_EINVAL);
+
+    /* Suspend the sound devices.
+     * Don't want to remove port while port is being accessed by sound
+     * device's threads!
+     */
+
+    pj_mutex_lock(conf->mutex);
+
+    /* Port must be valid. */
+    conf_port = conf->ports[port];
+    if (conf_port == NULL) {
+	pj_mutex_unlock(conf->mutex);
+	return PJ_EINVAL;
+    }
+
+    conf_port->tx_setting = PJMEDIA_PORT_DISABLE;
+    conf_port->rx_setting = PJMEDIA_PORT_DISABLE;
+
+    /* Remove this port from transmit array of other ports. */
+    for (i=0; i<conf->max_ports; ++i) {
+	unsigned j;
+	struct conf_port *src_port;
+
+	src_port = conf->ports[i];
+
+	if (!src_port)
+	    continue;
+
+	if (src_port->listener_cnt == 0)
+	    continue;
+
+	for (j=0; j<src_port->listener_cnt; ++j) {
+	    if (src_port->listener_slots[j] == port) {
+		pj_array_erase(src_port->listener_slots, sizeof(SLOT_TYPE),
+			       src_port->listener_cnt, j);
+		pj_assert(conf->connect_cnt > 0);
+		--conf->connect_cnt;
+		--src_port->listener_cnt;
+		break;
+	    }
+	}
+    }
+
+    /* Update transmitter_cnt of ports we're transmitting to */
+    while (conf_port->listener_cnt) {
+	unsigned dst_slot;
+	struct conf_port *dst_port;
+
+	dst_slot = conf_port->listener_slots[conf_port->listener_cnt-1];
+	dst_port = conf->ports[dst_slot];
+	--dst_port->transmitter_cnt;
+	--conf_port->listener_cnt;
+	pj_assert(conf->connect_cnt > 0);
+	--conf->connect_cnt;
+    }
+
+    /* Destroy pjmedia port if this conf port is passive port,
+     * i.e: has delay buf.
+     */
+    if (conf_port->delay_buf) {
+	pjmedia_port_destroy(conf_port->port);
+	conf_port->port = NULL;
+    }
+
+    /* Remove the port. */
+    conf->ports[port] = NULL;
+    --conf->port_cnt;
+
+    pj_mutex_unlock(conf->mutex);
+
+
+    /* Stop sound if there's no connection. */
+    if (conf->connect_cnt == 0) {
+	pause_sound(conf);
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Enum ports.
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_enum_ports( pjmedia_conf *conf,
+					     unsigned ports[],
+					     unsigned *p_count )
+{
+    unsigned i, count=0;
+
+    PJ_ASSERT_RETURN(conf && p_count && ports, PJ_EINVAL);
+
+    /* Lock mutex */
+    pj_mutex_lock(conf->mutex);
+
+    for (i=0; i<conf->max_ports && count<*p_count; ++i) {
+	if (!conf->ports[i])
+	    continue;
+
+	ports[count++] = i;
+    }
+
+    /* Unlock mutex */
+    pj_mutex_unlock(conf->mutex);
+
+    *p_count = count;
+    return PJ_SUCCESS;
+}
+
+/*
+ * Get port info
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_get_port_info( pjmedia_conf *conf,
+						unsigned slot,
+						pjmedia_conf_port_info *info)
+{
+    struct conf_port *conf_port;
+
+    /* Check arguments */
+    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
+
+    /* Lock mutex */
+    pj_mutex_lock(conf->mutex);
+
+    /* Port must be valid. */
+    conf_port = conf->ports[slot];
+    if (conf_port == NULL) {
+	pj_mutex_unlock(conf->mutex);
+	return PJ_EINVAL;
+    }
+
+    info->slot = slot;
+    info->name = conf_port->name;
+    info->tx_setting = conf_port->tx_setting;
+    info->rx_setting = conf_port->rx_setting;
+    info->listener_cnt = conf_port->listener_cnt;
+    info->listener_slots = conf_port->listener_slots;
+    info->transmitter_cnt = conf_port->transmitter_cnt;
+    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->tx_adj_level = conf_port->tx_adj_level - NORMAL_LEVEL;
+    info->rx_adj_level = conf_port->rx_adj_level - NORMAL_LEVEL;
+
+    /* Unlock mutex */
+    pj_mutex_unlock(conf->mutex);
+
+    return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pjmedia_conf_get_ports_info(pjmedia_conf *conf,
+						unsigned *size,
+						pjmedia_conf_port_info info[])
+{
+    unsigned i, count=0;
+
+    PJ_ASSERT_RETURN(conf && size && info, PJ_EINVAL);
+
+    /* Lock mutex */
+    pj_mutex_lock(conf->mutex);
+
+    for (i=0; i<conf->max_ports && count<*size; ++i) {
+	if (!conf->ports[i])
+	    continue;
+
+	pjmedia_conf_get_port_info(conf, i, &info[count]);
+	++count;
+    }
+
+    /* Unlock mutex */
+    pj_mutex_unlock(conf->mutex);
+
+    *size = count;
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Get signal level.
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_get_signal_level( pjmedia_conf *conf,
+						   unsigned slot,
+						   unsigned *tx_level,
+						   unsigned *rx_level)
+{
+    struct conf_port *conf_port;
+
+    /* Check arguments */
+    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
+
+    /* Lock mutex */
+    pj_mutex_lock(conf->mutex);
+
+    /* Port must be valid. */
+    conf_port = conf->ports[slot];
+    if (conf_port == NULL) {
+	pj_mutex_unlock(conf->mutex);
+	return PJ_EINVAL;
+    }
+
+    if (tx_level != NULL) {
+	*tx_level = conf_port->tx_level;
+    }
+
+    if (rx_level != NULL) 
+	*rx_level = conf_port->rx_level;
+
+    /* Unlock mutex */
+    pj_mutex_unlock(conf->mutex);
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Adjust RX level of individual port.
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_adjust_rx_level( pjmedia_conf *conf,
+						  unsigned slot,
+						  int adj_level )
+{
+    struct conf_port *conf_port;
+
+    /* Check arguments */
+    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
+
+    /* Value must be from -128 to +127 */
+    /* Disabled, you can put more than +127, at your own risk: 
+     PJ_ASSERT_RETURN(adj_level >= -128 && adj_level <= 127, PJ_EINVAL);
+     */
+    PJ_ASSERT_RETURN(adj_level >= -128, PJ_EINVAL);
+
+    /* Lock mutex */
+    pj_mutex_lock(conf->mutex);
+
+    /* Port must be valid. */
+    conf_port = conf->ports[slot];
+    if (conf_port == NULL) {
+	pj_mutex_unlock(conf->mutex);
+	return PJ_EINVAL;
+    }
+
+    /* Set normalized adjustment level. */
+    conf_port->rx_adj_level = adj_level + NORMAL_LEVEL;
+
+    /* Unlock mutex */
+    pj_mutex_unlock(conf->mutex);
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Adjust TX level of individual port.
+ */
+PJ_DEF(pj_status_t) pjmedia_conf_adjust_tx_level( pjmedia_conf *conf,
+						  unsigned slot,
+						  int adj_level )
+{
+    struct conf_port *conf_port;
+
+    /* Check arguments */
+    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
+
+    /* Value must be from -128 to +127 */
+    /* Disabled, you can put more than +127,, at your own risk:
+     PJ_ASSERT_RETURN(adj_level >= -128 && adj_level <= 127, PJ_EINVAL);
+     */
+    PJ_ASSERT_RETURN(adj_level >= -128, PJ_EINVAL);
+
+    /* Lock mutex */
+    pj_mutex_lock(conf->mutex);
+
+    /* Port must be valid. */
+    conf_port = conf->ports[slot];
+    if (conf_port == NULL) {
+	pj_mutex_unlock(conf->mutex);
+	return PJ_EINVAL;
+    }
+
+    /* Set normalized adjustment level. */
+    conf_port->tx_adj_level = adj_level + NORMAL_LEVEL;
+
+    /* Unlock mutex */
+    pj_mutex_unlock(conf->mutex);
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Read from port.
+ */
+static pj_status_t read_port( pjmedia_conf *conf,
+			      struct conf_port *cport, pj_int16_t *frame,
+			      pj_size_t count, pjmedia_frame_type *type )
+{
+
+    pj_assert(count == conf->samples_per_frame);
+
+    TRACE_((THIS_FILE, "read_port %.*s: count=%d", 
+		       (int)cport->name.slen, cport->name.ptr,
+		       count));
+
+    /* 
+     * If port's samples per frame and sampling rate and channel count
+     * matche conference bridge's settings, get the frame directly from
+     * the port.
+     */
+    if (cport->rx_buf_cap == 0) {
+	pjmedia_frame f;
+	pj_status_t status;
+
+	f.buf = frame;
+	f.size = count * BYTES_PER_SAMPLE;
+
+	TRACE_((THIS_FILE, "  get_frame %.*s: count=%d", 
+		   (int)cport->name.slen, cport->name.ptr,
+		   count));
+
+	status = pjmedia_port_get_frame(cport->port, &f);
+
+	*type = f.type;
+
+	return status;
+
+    } else {
+	unsigned samples_req;
+
+	/* Initialize frame type */
+	if (cport->rx_buf_count == 0) {
+	    *type = PJMEDIA_FRAME_TYPE_NONE;
+	} else {
+	    /* we got some samples in the buffer */
+	    *type = PJMEDIA_FRAME_TYPE_AUDIO;
+	}
+
+	/*
+	 * If we don't have enough samples in rx_buf, read from the port 
+	 * first. Remember that rx_buf may be in different clock rate and
+	 * channel count!
+	 */
+
+	samples_req = (unsigned) (count * 1.0 * 
+		      cport->clock_rate / conf->clock_rate + 0.5);
+
+	while (cport->rx_buf_count < samples_req) {
+
+	    pjmedia_frame f;
+	    pj_status_t status;
+
+	    f.buf = cport->rx_buf + cport->rx_buf_count;
+	    f.size = cport->samples_per_frame * BYTES_PER_SAMPLE;
+
+	    TRACE_((THIS_FILE, "  get_frame, count=%d", 
+		       cport->samples_per_frame));
+
+	    status = pjmedia_port_get_frame(cport->port, &f);
+
+	    if (status != PJ_SUCCESS) {
+		/* Fatal error! */
+		return status;
+	    }
+
+	    if (f.type != PJMEDIA_FRAME_TYPE_AUDIO) {
+		TRACE_((THIS_FILE, "  get_frame returned non-audio"));
+		pjmedia_zero_samples( cport->rx_buf + cport->rx_buf_count,
+				      cport->samples_per_frame);
+	    } else {
+		/* We've got at least one frame */
+		*type = PJMEDIA_FRAME_TYPE_AUDIO;
+	    }
+
+	    /* Adjust channels */
+	    if (cport->channel_count != conf->channel_count) {
+		if (cport->channel_count == 1) {
+		    pjmedia_convert_channel_1ton((pj_int16_t*)f.buf, 
+						 (const pj_int16_t*)f.buf,
+						 conf->channel_count, 
+						 cport->samples_per_frame,
+						 0);
+		    cport->rx_buf_count += (cport->samples_per_frame * 
+					    conf->channel_count);
+		} else { /* conf->channel_count == 1 */
+		    pjmedia_convert_channel_nto1((pj_int16_t*)f.buf, 
+						 (const pj_int16_t*)f.buf,
+						 cport->channel_count, 
+						 cport->samples_per_frame, 
+						 PJMEDIA_STEREO_MIX, 0);
+		    cport->rx_buf_count += (cport->samples_per_frame / 
+					    cport->channel_count);
+		}
+	    } else {
+		cport->rx_buf_count += cport->samples_per_frame;
+	    }
+
+	    TRACE_((THIS_FILE, "  rx buffer size is now %d",
+		    cport->rx_buf_count));
+
+	    pj_assert(cport->rx_buf_count <= cport->rx_buf_cap);
+	}
+
+	/*
+	 * If port's clock_rate is different, resample.
+	 * Otherwise just copy.
+	 */
+	if (cport->clock_rate != conf->clock_rate) {
+	    
+	    unsigned src_count;
+
+	    TRACE_((THIS_FILE, "  resample, input count=%d", 
+		    pjmedia_resample_get_input_size(cport->rx_resample)));
+
+	    pjmedia_resample_run( cport->rx_resample,cport->rx_buf, frame);
+
+	    src_count = (unsigned)(count * 1.0 * cport->clock_rate / 
+				   conf->clock_rate + 0.5);
+	    cport->rx_buf_count -= src_count;
+	    if (cport->rx_buf_count) {
+		pjmedia_move_samples(cport->rx_buf, cport->rx_buf+src_count,
+				     cport->rx_buf_count);
+	    }
+
+	    TRACE_((THIS_FILE, "  rx buffer size is now %d",
+		    cport->rx_buf_count));
+
+	} else {
+
+	    pjmedia_copy_samples(frame, cport->rx_buf, (unsigned)count);
+	    cport->rx_buf_count -= (unsigned)count;
+	    if (cport->rx_buf_count) {
+		pjmedia_move_samples(cport->rx_buf, cport->rx_buf+count,
+				     cport->rx_buf_count);
+	    }
+	}
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Write the mixed signal to the port.
+ */
+static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport,
+			      const pj_timestamp *timestamp, 
+			      pjmedia_frame_type *frm_type)
+{
+    pj_int16_t *buf;
+    unsigned j, ts;
+    pj_status_t status;
+    pj_int32_t adj_level;
+    pj_int32_t tx_level;
+    unsigned dst_count;
+
+    *frm_type = PJMEDIA_FRAME_TYPE_AUDIO;
+
+    /* If port is muted or nobody is transmitting to this port, 
+     * transmit NULL frame. 
+     */
+    if (cport->tx_setting == PJMEDIA_PORT_MUTE || cport->transmitter_cnt==0) {
+
+	pjmedia_frame frame;
+
+	/* Clear left-over samples in tx_buffer, if any, so that it won't
+	 * be transmitted next time we have audio signal.
+	 */
+	cport->tx_buf_count = 0;
+
+	/* Add sample counts to heart-beat samples */
+	cport->tx_heart_beat += conf->samples_per_frame * cport->clock_rate /
+				conf->clock_rate * 
+				cport->channel_count / conf->channel_count;
+
+	/* Set frame timestamp */
+	frame.timestamp.u64 = timestamp->u64 * cport->clock_rate /
+				conf->clock_rate;
+	frame.type = PJMEDIA_FRAME_TYPE_NONE;
+	frame.buf = NULL;
+	frame.size = 0;
+
+	/* Transmit heart-beat frames (may transmit more than one NULL frame
+	 * if port's ptime is less than bridge's ptime.
+	 */
+	if (cport->port && cport->port->put_frame) {
+	    while (cport->tx_heart_beat >= cport->samples_per_frame) {
+
+		pjmedia_port_put_frame(cport->port, &frame);
+
+		cport->tx_heart_beat -= cport->samples_per_frame;
+		frame.timestamp.u64 += cport->samples_per_frame;
+	    }
+	}
+
+	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;
+    }
+
+    /* Reset heart-beat sample count */
+    cport->tx_heart_beat = 0;
+
+    buf = (pj_int16_t*) cport->mix_buf;
+
+    /* If there are sources in the mix buffer, convert the mixed samples
+     * from 32bit to 16bit in the mixed samples itself. This is possible 
+     * because mixed sample is 32bit.
+     *
+     * In addition to this process, if we need to change the level of
+     * TX signal, we adjust is here too.
+     */
+
+    /* Calculate signal level and adjust the signal when needed. 
+     * Two adjustments performed at once: 
+     * 1. user setting adjustment (tx_adj_level). 
+     * 2. automatic adjustment of overflowed mixed buffer (mix_adj).
+     */
+
+    /* Apply simple AGC to the mix_adj, the automatic adjust, to avoid 
+     * dramatic change in the level thus causing noise because the signal 
+     * is now not aligned with the signal from the previous frame.
+     */
+    SIMPLE_AGC(cport->last_mix_adj, cport->mix_adj);
+    cport->last_mix_adj = cport->mix_adj;
+
+    /* adj_level = cport->tx_adj_level * cport->mix_adj / NORMAL_LEVEL;*/
+    adj_level = cport->tx_adj_level * cport->mix_adj;
+    adj_level >>= 7;
+
+    tx_level = 0;
+
+    if (adj_level != NORMAL_LEVEL) {
+	for (j=0; j<conf->samples_per_frame; ++j) {
+	    pj_int32_t itemp = cport->mix_buf[j];
+
+	    /* Adjust the level */
+	    /*itemp = itemp * adj_level / NORMAL_LEVEL;*/
+	    itemp = (itemp * adj_level) >> 7;
+
+	    /* Clip the signal if it's too loud */
+	    if (itemp > MAX_LEVEL) itemp = MAX_LEVEL;
+	    else if (itemp < MIN_LEVEL) itemp = MIN_LEVEL;
+
+	    /* Put back in the buffer. */
+	    buf[j] = (pj_int16_t) itemp;
+
+	    tx_level += (buf[j]>=0? buf[j] : -buf[j]);
+	}
+    } else {
+	for (j=0; j<conf->samples_per_frame; ++j) {
+	    buf[j] = (pj_int16_t) cport->mix_buf[j];
+	    tx_level += (buf[j]>=0? buf[j] : -buf[j]);
+	}
+    }
+
+    tx_level /= conf->samples_per_frame;
+
+    /* Convert level to 8bit complement ulaw */
+    tx_level = pjmedia_linear2ulaw(tx_level) ^ 0xff;
+
+    cport->tx_level = tx_level;
+
+    /* If port has the same clock_rate and samples_per_frame and 
+     * number of channels as the conference bridge, transmit the 
+     * frame as is.
+     */
+    if (cport->clock_rate == conf->clock_rate &&
+	cport->samples_per_frame == conf->samples_per_frame &&
+	cport->channel_count == conf->channel_count)
+    {
+	if (cport->port != NULL) {
+	    pjmedia_frame frame;
+
+	    frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
+	    frame.buf = buf;
+	    frame.size = conf->samples_per_frame * BYTES_PER_SAMPLE;
+	    /* No need to adjust timestamp, port has the same
+	     * clock rate as conference bridge 
+	     */
+	    frame.timestamp = *timestamp;
+
+	    TRACE_((THIS_FILE, "put_frame %.*s, count=%d", 
+			       (int)cport->name.slen, cport->name.ptr,
+			       frame.size / BYTES_PER_SAMPLE));
+
+	    return pjmedia_port_put_frame(cport->port, &frame);
+	} else
+	    return PJ_SUCCESS;
+    }
+
+    /* If it has different clock_rate, must resample. */
+    if (cport->clock_rate != conf->clock_rate) {
+	pjmedia_resample_run( cport->tx_resample, buf, 
+			      cport->tx_buf + cport->tx_buf_count );
+	dst_count = (unsigned)(conf->samples_per_frame * 1.0 *
+			       cport->clock_rate / conf->clock_rate + 0.5);
+    } else {
+	/* Same clock rate.
+	 * Just copy the samples to tx_buffer.
+	 */
+	pjmedia_copy_samples( cport->tx_buf + cport->tx_buf_count,
+			      buf, conf->samples_per_frame );
+	dst_count = conf->samples_per_frame;
+    }
+
+    /* Adjust channels */
+    if (cport->channel_count != conf->channel_count) {
+	pj_int16_t *tx_buf = cport->tx_buf + cport->tx_buf_count;
+	if (conf->channel_count == 1) {
+	    pjmedia_convert_channel_1ton(tx_buf, tx_buf,
+					 cport->channel_count, 
+					 dst_count, 0);
+	    dst_count *= cport->channel_count;
+	} else { /* cport->channel_count == 1 */
+	    pjmedia_convert_channel_nto1(tx_buf, tx_buf,
+					 conf->channel_count, 
+					 dst_count, PJMEDIA_STEREO_MIX, 0);
+	    dst_count /= conf->channel_count;
+	}
+    }
+
+    cport->tx_buf_count += dst_count;
+
+    pj_assert(cport->tx_buf_count <= cport->tx_buf_cap);
+
+    /* Transmit while we have enough frame in the tx_buf. */
+    status = PJ_SUCCESS;
+    ts = 0;
+    while (cport->tx_buf_count >= cport->samples_per_frame &&
+	   status == PJ_SUCCESS) 
+    {
+	
+	TRACE_((THIS_FILE, "write_port %.*s: count=%d", 
+			   (int)cport->name.slen, cport->name.ptr,
+			   cport->samples_per_frame));
+
+	if (cport->port) {
+	    pjmedia_frame frame;
+
+	    frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
+	    frame.buf = cport->tx_buf;
+	    frame.size = cport->samples_per_frame * BYTES_PER_SAMPLE;
+	    /* Adjust timestamp as port may have different clock rate
+	     * than the bridge.
+	     */
+	    frame.timestamp.u64 = timestamp->u64 * cport->clock_rate /
+				  conf->clock_rate;
+
+	    /* Add timestamp for individual frame */
+	    frame.timestamp.u64 += ts;
+	    ts += cport->samples_per_frame;
+
+	    TRACE_((THIS_FILE, "put_frame %.*s, count=%d", 
+			       (int)cport->name.slen, cport->name.ptr,
+			       frame.size / BYTES_PER_SAMPLE));
+
+	    status = pjmedia_port_put_frame(cport->port, &frame);
+
+	} else
+	    status = PJ_SUCCESS;
+
+	cport->tx_buf_count -= cport->samples_per_frame;
+	if (cport->tx_buf_count) {
+	    pjmedia_move_samples(cport->tx_buf, 
+				 cport->tx_buf + cport->samples_per_frame,
+				 cport->tx_buf_count);
+	}
+
+	TRACE_((THIS_FILE, " tx_buf count now is %d", 
+			   cport->tx_buf_count));
+    }
+
+    return status;
+}
+
+
+/*
+ * Player callback.
+ */
+static pj_status_t get_frame(pjmedia_port *this_port, 
+			     pjmedia_frame *frame)
+{
+    pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata;
+    pjmedia_frame_type speaker_frame_type = PJMEDIA_FRAME_TYPE_NONE;
+    unsigned ci, cj, i, j;
+    pj_int16_t *p_in;
+    
+    TRACE_((THIS_FILE, "- clock -"));
+
+    /* Check that correct size is specified. */
+    pj_assert(frame->size == conf->samples_per_frame *
+			     conf->bits_per_sample / 8);
+
+    /* Must lock mutex */
+    pj_mutex_lock(conf->mutex);
+
+    /* Reset port source count. We will only reset port's mix
+     * buffer when we have someone transmitting to it.
+     */
+    for (i=0, ci=0; i<conf->max_ports && ci < conf->port_cnt; ++i) {
+	struct conf_port *conf_port = conf->ports[i];
+
+	/* Skip empty port. */
+	if (!conf_port)
+	    continue;
+
+	/* Var "ci" is to count how many ports have been visited so far. */
+	++ci;
+
+	/* Reset buffer (only necessary if the port has transmitter) and
+	 * reset auto adjustment level for mixed signal.
+	 */
+	conf_port->mix_adj = NORMAL_LEVEL;
+	if (conf_port->transmitter_cnt) {
+	    pj_bzero(conf_port->mix_buf,
+		     conf->samples_per_frame*sizeof(conf_port->mix_buf[0]));
+	}
+    }
+
+    /* Get frames from all ports, and "mix" the signal 
+     * to mix_buf of all listeners of the port.
+     */
+    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 = 0;
+
+	/* Skip empty port. */
+	if (!conf_port)
+	    continue;
+
+	/* Var "ci" is to count how many ports have been visited so far. */
+	++ci;
+
+	/* Skip if we're not allowed to receive from this port. */
+	if (conf_port->rx_setting == PJMEDIA_PORT_DISABLE) {
+	    conf_port->rx_level = 0;
+	    continue;
+	}
+
+	/* Also skip if this port doesn't have listeners. */
+	if (conf_port->listener_cnt == 0) {
+	    conf_port->rx_level = 0;
+	    continue;
+	}
+
+	/* Get frame from this port.
+	 * For passive ports, get the frame from the delay_buf.
+	 * For other ports, get the frame from the port. 
+	 */
+	if (conf_port->delay_buf != NULL) {
+	    pj_status_t status;
+	
+	    status = pjmedia_delay_buf_get(conf_port->delay_buf,
+				  (pj_int16_t*)frame->buf);
+	    if (status != PJ_SUCCESS)
+		continue;
+
+	} else {
+
+	    pj_status_t status;
+	    pjmedia_frame_type frame_type;
+
+	    status = read_port(conf, conf_port, (pj_int16_t*)frame->buf, 
+			       conf->samples_per_frame, &frame_type);
+	    
+	    if (status != PJ_SUCCESS) {
+		/* bennylp: why do we need this????
+		 * Also see comments on similar issue with write_port().
+		PJ_LOG(4,(THIS_FILE, "Port %.*s get_frame() returned %d. "
+				     "Port is now disabled",
+				     (int)conf_port->name.slen,
+				     conf_port->name.ptr,
+				     status));
+		conf_port->rx_setting = PJMEDIA_PORT_DISABLE;
+		 */
+		continue;
+	    }
+
+	    /* Check that the port is not removed when we call get_frame() */
+	    if (conf->ports[i] == NULL)
+		continue;
+
+	    /* Ignore if we didn't get any frame */
+	    if (frame_type != PJMEDIA_FRAME_TYPE_AUDIO)
+		continue;
+	}
+
+	p_in = (pj_int16_t*) frame->buf;
+
+	/* Adjust the RX level from this port
+	 * and calculate the average level at the same time.
+	 */
+	if (conf_port->rx_adj_level != NORMAL_LEVEL) {
+	    for (j=0; j<conf->samples_per_frame; ++j) {
+		/* For the level adjustment, we need to store the sample to
+		 * a temporary 32bit integer value to avoid overflowing the
+		 * 16bit sample storage.
+		 */
+		pj_int32_t itemp;
+
+		itemp = p_in[j];
+		/*itemp = itemp * adj / NORMAL_LEVEL;*/
+		/* bad code (signed/unsigned badness):
+		 *  itemp = (itemp * conf_port->rx_adj_level) >> 7;
+		 */
+		itemp *= conf_port->rx_adj_level;
+		itemp >>= 7;
+
+		/* Clip the signal if it's too loud */
+		if (itemp > MAX_LEVEL) itemp = MAX_LEVEL;
+		else if (itemp < MIN_LEVEL) itemp = MIN_LEVEL;
+
+		p_in[j] = (pj_int16_t) itemp;
+		level += (p_in[j]>=0? p_in[j] : -p_in[j]);
+	    }
+	} else {
+	    for (j=0; j<conf->samples_per_frame; ++j) {
+		level += (p_in[j]>=0? p_in[j] : -p_in[j]);
+	    }
+	}
+
+	level /= conf->samples_per_frame;
+
+	/* Convert level to 8bit complement ulaw */
+	level = pjmedia_linear2ulaw(level) ^ 0xff;
+
+	/* Put this level to port's last RX level. */
+	conf_port->rx_level = level;
+
+	// Ticket #671: Skipping very low audio signal may cause noise 
+	// to be generated in the remote end by some hardphones.
+	/* Skip processing frame if level is zero */
+	//if (level == 0)
+	//    continue;
+
+	/* Add the signal to all listeners. */
+	for (cj=0; cj < conf_port->listener_cnt; ++cj) 
+	{
+	    struct conf_port *listener;
+	    pj_int32_t *mix_buf;
+	    unsigned k;
+
+	    listener = conf->ports[conf_port->listener_slots[cj]];
+
+	    /* Skip if this listener doesn't want to receive audio */
+	    if (listener->tx_setting != PJMEDIA_PORT_ENABLE)
+		continue;
+
+	    mix_buf = listener->mix_buf;
+
+	    if (listener->transmitter_cnt > 1) {
+		/* Mixing signals,
+		 * and calculate appropriate level adjustment if there is
+		 * any overflowed level in the mixed signal.
+		 */
+		for (k=0; k < conf->samples_per_frame; ++k) {
+		    mix_buf[k] += p_in[k];
+		    /* Check if normalization adjustment needed. */
+		    if (IS_OVERFLOW(mix_buf[k])) {
+			/* NORMAL_LEVEL * MAX_LEVEL / mix_buf[k]; */
+			int tmp_adj = (MAX_LEVEL<<7) / mix_buf[k];
+			if (tmp_adj<0) tmp_adj = -tmp_adj;
+
+			if (tmp_adj<listener->mix_adj)
+			    listener->mix_adj = tmp_adj;
+
+		    } /* if any overflow in the mixed signals */
+		} /* loop mixing signals */
+	    } else {
+		/* Only 1 transmitter:
+		 * just copy the samples to the mix buffer
+		 * no mixing and level adjustment needed
+		 */
+		for (k=0; k<conf->samples_per_frame; ++k) {
+		    mix_buf[k] = p_in[k];
+		}
+	    }
+	} /* loop the listeners of conf port */
+    } /* loop of all conf ports */
+
+    /* Time for all ports to transmit whetever they have in their
+     * buffer. 
+     */
+    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;
+
+	if (!conf_port)
+	    continue;
+
+	/* Var "ci" is to count how many ports have been visited. */
+	++ci;
+
+	status = write_port( conf, conf_port, &frame->timestamp,
+			     &frm_type);
+	if (status != PJ_SUCCESS) {
+	    /* bennylp: why do we need this????
+	       One thing for sure, put_frame()/write_port() may return
+	       non-successfull status on Win32 if there's temporary glitch
+	       on network interface, so disabling the port here does not
+	       sound like a good idea.
+
+	    PJ_LOG(4,(THIS_FILE, "Port %.*s put_frame() returned %d. "
+				 "Port is now disabled",
+				 (int)conf_port->name.slen,
+				 conf_port->name.ptr,
+				 status));
+	    conf_port->tx_setting = PJMEDIA_PORT_DISABLE;
+	    */
+	    continue;
+	}
+
+	/* Set the type of frame to be returned to sound playback
+	 * device.
+	 */
+	if (i == 0)
+	    speaker_frame_type = frm_type;
+    }
+
+    /* Return sound playback frame. */
+    if (conf->ports[0]->tx_level) {
+	TRACE_((THIS_FILE, "write to audio, count=%d", 
+			   conf->samples_per_frame));
+	pjmedia_copy_samples( (pj_int16_t*)frame->buf, 
+			      (const pj_int16_t*)conf->ports[0]->mix_buf, 
+			      conf->samples_per_frame);
+    } else {
+	/* Force frame type NONE */
+	speaker_frame_type = PJMEDIA_FRAME_TYPE_NONE;
+    }
+
+    /* MUST set frame type */
+    frame->type = speaker_frame_type;
+
+    pj_mutex_unlock(conf->mutex);
+
+#ifdef REC_FILE
+    if (fhnd_rec == NULL)
+	fhnd_rec = fopen(REC_FILE, "wb");
+    if (fhnd_rec)
+	fwrite(frame->buf, frame->size, 1, fhnd_rec);
+#endif
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * get_frame() for passive port
+ */
+static pj_status_t get_frame_pasv(pjmedia_port *this_port, 
+				  pjmedia_frame *frame)
+{
+    pj_assert(0);
+    PJ_UNUSED_ARG(this_port);
+    PJ_UNUSED_ARG(frame);
+    return -1;
+}
+
+
+/*
+ * Recorder (or passive port) callback.
+ */
+static pj_status_t put_frame(pjmedia_port *this_port, 
+			     pjmedia_frame *frame)
+{
+    pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata;
+    struct conf_port *port = conf->ports[this_port->port_data.ldata];
+    pj_status_t status;
+
+    /* Check for correct size. */
+    PJ_ASSERT_RETURN( frame->size == conf->samples_per_frame *
+				     conf->bits_per_sample / 8,
+		      PJMEDIA_ENCSAMPLESPFRAME);
+
+    /* Check existance of delay_buf instance */
+    PJ_ASSERT_RETURN( port->delay_buf, PJ_EBUG );
+
+    /* Skip if this port is muted/disabled. */
+    if (port->rx_setting != PJMEDIA_PORT_ENABLE) {
+	return PJ_SUCCESS;
+    }
+
+    /* Skip if no port is listening to the microphone */
+    if (port->listener_cnt == 0) {
+	return PJ_SUCCESS;
+    }
+
+    status = pjmedia_delay_buf_put(port->delay_buf, (pj_int16_t*)frame->buf);
+
+    return status;
+}
+
+#endif
diff --git a/jni/pjproject-android/.svn/pristine/f1/f166252bcb46475aef827e128af7d0ccc6403492.svn-base b/jni/pjproject-android/.svn/pristine/f1/f166252bcb46475aef827e128af7d0ccc6403492.svn-base
new file mode 100644
index 0000000..12ca4aa
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f1/f166252bcb46475aef827e128af7d0ccc6403492.svn-base
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">

+<title>$title ($projectnumber)</title>

+<link href="/style/style.css" rel="stylesheet" type="text/css">

+</head><body>

+	<!--#include virtual="/header.html" -->

+	<p><A HREF="/">Home</A> --&gt; <A HREF="/docs.htm">Documentations</A> --&gt; PJLIB-UTIL Reference</p>

+

+

diff --git a/jni/pjproject-android/.svn/pristine/f1/f166479d55886b7f8aac94564122ed8167322012.svn-base b/jni/pjproject-android/.svn/pristine/f1/f166479d55886b7f8aac94564122ed8167322012.svn-base
new file mode 100644
index 0000000..e96f2a3
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f1/f166479d55886b7f8aac94564122ed8167322012.svn-base
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE scenario SYSTEM "sipp.dtd">
+
+<scenario name="Basic UAS responder">
+  <recv request="INVITE" crlf="true">
+  </recv>
+
+  <send>
+    <![CDATA[
+
+      SIP/2.0 100 Trying
+      [last_Via:]
+      [last_From:]
+      [last_To:]
+      [last_Call-ID:]
+      [last_CSeq:]
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+  <send>
+    <![CDATA[
+
+      SIP/2.0 180 Ringing
+      [last_Via:]
+      [last_From:]
+      [last_To:];tag=[call_number]
+      [last_Call-ID:]
+      [last_CSeq:]
+      Contact: <sip:192.168.0.15>
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+  <!-- Wait for CANCEL -->
+  <recv request="CANCEL" crlf="true">
+  </recv>
+
+  <send>
+    <![CDATA[
+      SIP/2.0 200 OK
+      [last_Via:]
+      [last_From:]
+      [last_To:]
+      [last_Call-ID:]
+      [last_CSeq:]
+      Content-Length: 0
+
+    ]]>
+  </send>
+
+
+  <!-- definition of the response time repartition table (unit is ms)   -->
+  <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
+
+  <!-- definition of the call length repartition table (unit is ms)     -->
+  <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
+
+</scenario>
+
diff --git a/jni/pjproject-android/.svn/pristine/f1/f17f6c7ddb7a1df1de25dac8854e3508e38dd2df.svn-base b/jni/pjproject-android/.svn/pristine/f1/f17f6c7ddb7a1df1de25dac8854e3508e38dd2df.svn-base
new file mode 100644
index 0000000..5ae855f
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f1/f17f6c7ddb7a1df1de25dac8854e3508e38dd2df.svn-base
@@ -0,0 +1,53 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "speex/speex_echo.h"
+#include "speex/speex_preprocess.h"
+
+
+#define NN 128
+#define TAIL 1024
+
+int main(int argc, char **argv)
+{
+   FILE *echo_fd, *ref_fd, *e_fd;
+   short echo_buf[NN], ref_buf[NN], e_buf[NN];
+   SpeexEchoState *st;
+   SpeexPreprocessState *den;
+   int sampleRate = 8000;
+
+   if (argc != 4)
+   {
+      fprintf(stderr, "testecho mic_signal.sw speaker_signal.sw output.sw\n");
+      exit(1);
+   }
+   echo_fd = fopen(argv[2], "rb");
+   ref_fd  = fopen(argv[1],  "rb");
+   e_fd    = fopen(argv[3], "wb");
+
+   st = speex_echo_state_init(NN, TAIL);
+   den = speex_preprocess_state_init(NN, sampleRate);
+   speex_echo_ctl(st, SPEEX_ECHO_SET_SAMPLING_RATE, &sampleRate);
+   speex_preprocess_ctl(den, SPEEX_PREPROCESS_SET_ECHO_STATE, st);
+
+   while (!feof(ref_fd) && !feof(echo_fd))
+   {
+      fread(ref_buf, sizeof(short), NN, ref_fd);
+      fread(echo_buf, sizeof(short), NN, echo_fd);
+      speex_echo_cancellation(st, ref_buf, echo_buf, e_buf);
+      speex_preprocess_run(den, e_buf);
+      fwrite(e_buf, sizeof(short), NN, e_fd);
+   }
+   speex_echo_state_destroy(st);
+   speex_preprocess_state_destroy(den);
+   fclose(e_fd);
+   fclose(echo_fd);
+   fclose(ref_fd);
+   return 0;
+}
diff --git a/jni/pjproject-android/.svn/pristine/f1/f186e392ce745e27c7ae7f71490a5a4b39545786.svn-base b/jni/pjproject-android/.svn/pristine/f1/f186e392ce745e27c7ae7f71490a5a4b39545786.svn-base
new file mode 100644
index 0000000..70bf6f7
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f1/f186e392ce745e27c7ae7f71490a5a4b39545786.svn-base
@@ -0,0 +1,1033 @@
+# Doxyfile 1.3-rc3

+

+# This file describes the settings to be used by the documentation system

+# doxygen (www.doxygen.org) for a project

+#

+# All text after a hash (#) is considered a comment and will be ignored

+# The format is:

+#       TAG = value [value, ...]

+# For lists items can also be appended using:

+#       TAG += value [value, ...]

+# Values that contain spaces should be placed between quotes (" ")

+

+#---------------------------------------------------------------------------

+# General configuration options

+#---------------------------------------------------------------------------

+

+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 

+# by quotes) that should identify the project.

+

+PROJECT_NAME           =  "PJNATH Reference"

+

+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 

+# This could be handy for archiving the generated documentation or 

+# if some version control system is used.

+

+PROJECT_NUMBER         = $(PJ_VERSION)

+

+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 

+# base path where the generated documentation will be put. 

+# If a relative path is entered, it will be relative to the location 

+# where doxygen was started. If left blank the current directory will be used.

+

+OUTPUT_DIRECTORY       = docs/$(PJ_VERSION)

+

+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 

+# documentation generated by doxygen is written. Doxygen will use this 

+# information to generate all constant output in the proper language. 

+# The default language is English, other supported languages are: 

+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, 

+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en 

+# (Japanese with english messages), Korean, Norwegian, Polish, Portuguese, 

+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish and Ukrainian.

+

+OUTPUT_LANGUAGE        = English

+

+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 

+# documentation are documented, even if no documentation was available. 

+# Private class members and static file members will be hidden unless 

+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES

+

+EXTRACT_ALL            = NO

+

+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 

+# will be included in the documentation.

+

+EXTRACT_PRIVATE        = NO

+

+# If the EXTRACT_STATIC tag is set to YES all static members of a file 

+# will be included in the documentation.

+

+EXTRACT_STATIC         = NO

+

+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 

+# defined locally in source files will be included in the documentation. 

+# If set to NO only classes defined in header files are included.

+

+EXTRACT_LOCAL_CLASSES  = YES

+

+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 

+# undocumented members of documented classes, files or namespaces. 

+# If set to NO (the default) these members will be included in the 

+# various overviews, but no documentation section is generated. 

+# This option has no effect if EXTRACT_ALL is enabled.

+

+HIDE_UNDOC_MEMBERS     = NO

+

+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 

+# undocumented classes that are normally visible in the class hierarchy. 

+# If set to NO (the default) these class will be included in the various 

+# overviews. This option has no effect if EXTRACT_ALL is enabled.

+

+HIDE_UNDOC_CLASSES     = NO

+

+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 

+# friend (class|struct|union) declarations. 

+# If set to NO (the default) these declarations will be included in the 

+# documentation.

+

+HIDE_FRIEND_COMPOUNDS  = NO

+

+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 

+# documentation blocks found inside the body of a function. 

+# If set to NO (the default) these blocks will be appended to the 

+# function's detailed documentation block.

+

+HIDE_IN_BODY_DOCS      = NO

+

+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 

+# include brief member descriptions after the members that are listed in 

+# the file and class documentation (similar to JavaDoc). 

+# Set to NO to disable this.

+

+BRIEF_MEMBER_DESC      = YES

+

+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 

+# the brief description of a member or function before the detailed description. 

+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 

+# brief descriptions will be completely suppressed.

+

+REPEAT_BRIEF           = NO

+

+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 

+# Doxygen will generate a detailed section even if there is only a brief 

+# description.

+

+ALWAYS_DETAILED_SEC    = NO

+

+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited 

+# members of a class in the documentation of that class as if those members were 

+# ordinary class members. Constructors, destructors and assignment operators of 

+# the base classes will not be shown.

+

+INLINE_INHERITED_MEMB  = NO

+

+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 

+# path before files name in the file list and in the header files. If set 

+# to NO the shortest path that makes the file name unique will be used.

+

+FULL_PATH_NAMES        = NO

+

+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 

+# can be used to strip a user defined part of the path. Stripping is 

+# only done if one of the specified strings matches the left-hand part of 

+# the path. It is allowed to use relative paths in the argument list.

+

+STRIP_FROM_PATH        = "c:\project\pjproject"

+

+# The INTERNAL_DOCS tag determines if documentation 

+# that is typed after a \internal command is included. If the tag is set 

+# to NO (the default) then the documentation will be excluded. 

+# Set it to YES to include the internal documentation.

+

+INTERNAL_DOCS          = NO

+

+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 

+# file names in lower case letters. If set to YES upper case letters are also 

+# allowed. This is useful if you have classes or files whose names only differ 

+# in case and if your file system supports case sensitive file names. Windows 

+# users are adviced to set this option to NO.

+

+CASE_SENSE_NAMES       = YES

+

+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 

+# (but less readable) file names. This can be useful is your file systems 

+# doesn't support long names like on DOS, Mac, or CD-ROM.

+

+SHORT_NAMES            = NO

+

+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 

+# will show members with their full class and namespace scopes in the 

+# documentation. If set to YES the scope will be hidden.

+

+HIDE_SCOPE_NAMES       = NO

+

+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 

+# will generate a verbatim copy of the header file for each class for 

+# which an include is specified. Set to NO to disable this.

+

+VERBATIM_HEADERS       = YES

+

+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 

+# will put list of the files that are included by a file in the documentation 

+# of that file.

+

+SHOW_INCLUDE_FILES     = NO

+

+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 

+# will interpret the first line (until the first dot) of a JavaDoc-style 

+# comment as the brief description. If set to NO, the JavaDoc 

+# comments  will behave just like the Qt-style comments (thus requiring an 

+# explict @brief command for a brief description.

+

+JAVADOC_AUTOBRIEF      = NO

+

+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 

+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 

+# comments) as a brief description. This used to be the default behaviour. 

+# The new default is to treat a multi-line C++ comment block as a detailed 

+# description. Set this tag to YES if you prefer the old behaviour instead.

+

+MULTILINE_CPP_IS_BRIEF = NO

+

+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 

+# will output the detailed description near the top, like JavaDoc.

+# If set to NO, the detailed description appears after the member 

+# documentation.

+

+DETAILS_AT_TOP         = YES

+

+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 

+# member inherits the documentation from any documented member that it 

+# reimplements.

+

+INHERIT_DOCS           = YES

+

+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 

+# is inserted in the documentation for inline members.

+

+INLINE_INFO            = YES

+

+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 

+# will sort the (detailed) documentation of file and class members 

+# alphabetically by member name. If set to NO the members will appear in 

+# declaration order.

+

+SORT_MEMBER_DOCS       = YES

+

+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 

+# tag is set to YES, then doxygen will reuse the documentation of the first 

+# member in the group (if any) for the other members of the group. By default 

+# all members of a group must be documented explicitly.

+

+DISTRIBUTE_GROUP_DOC   = NO

+

+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 

+# Doxygen uses this value to replace tabs by spaces in code fragments.

+

+TAB_SIZE               = 8

+

+# The GENERATE_TODOLIST tag can be used to enable (YES) or 

+# disable (NO) the todo list. This list is created by putting \todo 

+# commands in the documentation.

+

+GENERATE_TODOLIST      = YES

+

+# The GENERATE_TESTLIST tag can be used to enable (YES) or 

+# disable (NO) the test list. This list is created by putting \test 

+# commands in the documentation.

+

+GENERATE_TESTLIST      = YES

+

+# The GENERATE_BUGLIST tag can be used to enable (YES) or 

+# disable (NO) the bug list. This list is created by putting \bug 

+# commands in the documentation.

+

+GENERATE_BUGLIST       = YES

+

+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 

+# disable (NO) the deprecated list. This list is created by putting 

+# \deprecated commands in the documentation.

+

+GENERATE_DEPRECATEDLIST= YES

+

+# This tag can be used to specify a number of aliases that acts 

+# as commands in the documentation. An alias has the form "name=value". 

+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 

+# put the command \sideeffect (or @sideeffect) in the documentation, which 

+# will result in a user defined paragraph with heading "Side Effects:". 

+# You can put \n's in the value part of an alias to insert newlines.

+

+ALIASES                = 

+

+# The ENABLED_SECTIONS tag can be used to enable conditional 

+# documentation sections, marked by \if sectionname ... \endif.

+

+ENABLED_SECTIONS       = 

+

+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 

+# the initial value of a variable or define consist of for it to appear in 

+# the documentation. If the initializer consists of more lines than specified 

+# here it will be hidden. Use a value of 0 to hide initializers completely. 

+# The appearance of the initializer of individual variables and defines in the 

+# documentation can be controlled using \showinitializer or \hideinitializer 

+# command in the documentation regardless of this setting.

+

+MAX_INITIALIZER_LINES  = 30

+

+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 

+# only. Doxygen will then generate output that is more tailored for C. 

+# For instance some of the names that are used will be different. The list 

+# of all members will be omitted, etc.

+

+OPTIMIZE_OUTPUT_FOR_C  = YES

+

+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 

+# only. Doxygen will then generate output that is more tailored for Java. 

+# For instance namespaces will be presented as packages, qualified scopes 

+# will look different, etc.

+

+OPTIMIZE_OUTPUT_JAVA   = NO

+

+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 

+# at the bottom of the documentation of classes and structs. If set to YES the 

+# list will mention the files that were used to generate the documentation.

+

+SHOW_USED_FILES        = YES

+TYPEDEF_HIDES_STRUCT	= YES

+

+#---------------------------------------------------------------------------

+# configuration options related to warning and progress messages

+#---------------------------------------------------------------------------

+

+# The QUIET tag can be used to turn on/off the messages that are generated 

+# by doxygen. Possible values are YES and NO. If left blank NO is used.

+

+QUIET                  = NO

+

+# The WARNINGS tag can be used to turn on/off the warning messages that are 

+# generated by doxygen. Possible values are YES and NO. If left blank 

+# NO is used.

+

+WARNINGS               = YES

+

+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 

+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 

+# automatically be disabled.

+

+WARN_IF_UNDOCUMENTED   = YES

+

+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 

+# potential errors in the documentation, such as not documenting some 

+# parameters in a documented function, or documenting parameters that 

+# don't exist or using markup commands wrongly.

+

+WARN_IF_DOC_ERROR      = YES

+

+# The WARN_FORMAT tag determines the format of the warning messages that 

+# doxygen can produce. The string should contain the $file, $line, and $text 

+# tags, which will be replaced by the file and line number from which the 

+# warning originated and the warning text.

+

+WARN_FORMAT            = "$file:$line: $text"

+

+# The WARN_LOGFILE tag can be used to specify a file to which warning 

+# and error messages should be written. If left blank the output is written 

+# to stderr.

+

+WARN_LOGFILE           = 

+

+#---------------------------------------------------------------------------

+# configuration options related to the input files

+#---------------------------------------------------------------------------

+

+# The INPUT tag can be used to specify the files and/or directories that contain 

+# documented source files. You may enter file names like "myfile.cpp" or 

+# directories like "/usr/src/myproject". Separate the files or directories 

+# with spaces.

+

+INPUT                  =  docs include/pjnath

+

+# If the value of the INPUT tag contains directories, you can use the 

+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 

+# and *.h) to filter out the source-files in the directories. If left 

+# blank the following patterns are tested: 

+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp 

+# *.h++ *.idl *.odl

+

+FILE_PATTERNS          = *.h *.c

+

+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 

+# should be searched for input files as well. Possible values are YES and NO. 

+# If left blank NO is used.

+

+RECURSIVE              = YES

+

+# The EXCLUDE tag can be used to specify files and/or directories that should 

+# excluded from the INPUT source files. This way you can easily exclude a 

+# subdirectory from a directory tree whose root is specified with the INPUT tag.

+

+EXCLUDE                = 

+

+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 

+# that are symbolic links (a Unix filesystem feature) are excluded from the input.

+

+EXCLUDE_SYMLINKS       = NO

+

+# If the value of the INPUT tag contains directories, you can use the 

+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 

+# certain files from those directories.

+

+EXCLUDE_PATTERNS       = "*_i.h" "*/compat/*"

+

+# The EXAMPLE_PATH tag can be used to specify one or more files or 

+# directories that contain example code fragments that are included (see 

+# the \include command).

+

+EXAMPLE_PATH           = ../pjsip-apps/src/samples src/pjturn-client

+

+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 

+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 

+# and *.h) to filter out the source-files in the directories. If left 

+# blank all files are included.

+

+EXAMPLE_PATTERNS       = 

+

+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 

+# searched for input files to be used with the \include or \dontinclude 

+# commands irrespective of the value of the RECURSIVE tag. 

+# Possible values are YES and NO. If left blank NO is used.

+

+EXAMPLE_RECURSIVE      = YES

+

+# The IMAGE_PATH tag can be used to specify one or more files or 

+# directories that contain image that are included in the documentation (see 

+# the \image command).

+

+IMAGE_PATH             =  docs

+

+# The INPUT_FILTER tag can be used to specify a program that doxygen should 

+# invoke to filter for each input file. Doxygen will invoke the filter program 

+# by executing (via popen()) the command <filter> <input-file>, where <filter> 

+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 

+# input file. Doxygen will then use the output that the filter program writes 

+# to standard output.

+

+INPUT_FILTER           = 

+

+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 

+# INPUT_FILTER) will be used to filter the input files when producing source 

+# files to browse (i.e. when SOURCE_BROWSER is set to YES).

+

+FILTER_SOURCE_FILES    = NO

+

+#---------------------------------------------------------------------------

+# configuration options related to source browsing

+#---------------------------------------------------------------------------

+

+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 

+# be generated. Documented entities will be cross-referenced with these sources.

+

+SOURCE_BROWSER         = NO

+

+# Setting the INLINE_SOURCES tag to YES will include the body 

+# of functions and classes directly in the documentation.

+

+INLINE_SOURCES         = NO

+

+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 

+# doxygen to hide any special comment blocks from generated source code 

+# fragments. Normal C and C++ comments will always remain visible.

+

+STRIP_CODE_COMMENTS    = YES

+

+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 

+# then for each documented function all documented 

+# functions referencing it will be listed.

+

+REFERENCED_BY_RELATION = YES

+

+# If the REFERENCES_RELATION tag is set to YES (the default) 

+# then for each documented function all documented entities 

+# called/used by that function will be listed.

+

+REFERENCES_RELATION    = YES

+

+#---------------------------------------------------------------------------

+# configuration options related to the alphabetical class index

+#---------------------------------------------------------------------------

+

+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 

+# of all compounds will be generated. Enable this if the project 

+# contains a lot of classes, structs, unions or interfaces.

+

+ALPHABETICAL_INDEX     = NO

+

+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 

+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 

+# in which this list will be split (can be a number in the range [1..20])

+

+COLS_IN_ALPHA_INDEX    = 5

+

+# In case all classes in a project start with a common prefix, all 

+# classes will be put under the same header in the alphabetical index. 

+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 

+# should be ignored while generating the index headers.

+

+IGNORE_PREFIX          = 

+

+#---------------------------------------------------------------------------

+# configuration options related to the HTML output

+#---------------------------------------------------------------------------

+

+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 

+# generate HTML output.

+

+GENERATE_HTML          = YES

+

+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 

+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 

+# put in front of it. If left blank `html' will be used as the default path.

+

+HTML_OUTPUT            = html

+

+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 

+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 

+# doxygen will generate files with .html extension.

+

+HTML_FILE_EXTENSION    = .htm

+

+# The HTML_HEADER tag can be used to specify a personal HTML header for 

+# each generated HTML page. If it is left blank doxygen will generate a 

+# standard header.

+

+HTML_HEADER            = docs/header.html

+

+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 

+# each generated HTML page. If it is left blank doxygen will generate a 

+# standard footer.

+

+HTML_FOOTER            = docs/footer.html

+

+# The HTML_STYLESHEET tag can be used to specify a user defined cascading 

+# style sheet that is used by each HTML page. It can be used to 

+# fine-tune the look of the HTML output. If the tag is left blank doxygen 

+# will generate a default style sheet

+

+HTML_STYLESHEET        = docs/doxygen.css

+

+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 

+# files or namespaces will be aligned in HTML using tables. If set to 

+# NO a bullet list will be used.

+

+HTML_ALIGN_MEMBERS     = YES

+

+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 

+# will be generated that can be used as input for tools like the 

+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 

+# of the generated HTML documentation.

+

+GENERATE_HTMLHELP      = NO

+

+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 

+# be used to specify the file name of the resulting .chm file. You 

+# can add a path in front of the file if the result should not be 

+# written to the html output dir.

+

+CHM_FILE               = 

+

+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 

+# be used to specify the location (absolute path including file name) of 

+# the HTML help compiler (hhc.exe). If non empty doxygen will try to run 

+# the html help compiler on the generated index.hhp.

+

+HHC_LOCATION           = 

+

+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 

+# controls if a separate .chi index file is generated (YES) or that 

+# it should be included in the master .chm file (NO).

+

+GENERATE_CHI           = NO

+

+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 

+# controls whether a binary table of contents is generated (YES) or a 

+# normal table of contents (NO) in the .chm file.

+

+BINARY_TOC             = NO

+

+# The TOC_EXPAND flag can be set to YES to add extra items for group members 

+# to the contents of the Html help documentation and to the tree view.

+

+TOC_EXPAND             = NO

+

+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 

+# top of each HTML page. The value NO (the default) enables the index and 

+# the value YES disables it.

+

+DISABLE_INDEX          = NO

+

+# This tag can be used to set the number of enum values (range [1..20]) 

+# that doxygen will group on one line in the generated HTML documentation.

+

+ENUM_VALUES_PER_LINE   = 1

+

+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be

+# generated containing a tree-like index structure (just like the one that 

+# is generated for HTML Help). For this to work a browser that supports 

+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla, 

+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 

+# probably better off using the HTML help feature.

+

+GENERATE_TREEVIEW      = NO

+

+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 

+# used to set the initial width (in pixels) of the frame in which the tree 

+# is shown.

+

+TREEVIEW_WIDTH         = 250

+

+#---------------------------------------------------------------------------

+# configuration options related to the LaTeX output

+#---------------------------------------------------------------------------

+

+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 

+# generate Latex output.

+

+GENERATE_LATEX         = NO

+

+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 

+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 

+# put in front of it. If left blank `latex' will be used as the default path.

+

+LATEX_OUTPUT           = latex

+

+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 

+# invoked. If left blank `latex' will be used as the default command name.

+

+LATEX_CMD_NAME         = latex

+

+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 

+# generate index for LaTeX. If left blank `makeindex' will be used as the 

+# default command name.

+

+MAKEINDEX_CMD_NAME     = makeindex

+

+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 

+# LaTeX documents. This may be useful for small projects and may help to 

+# save some trees in general.

+

+COMPACT_LATEX          = NO

+

+# The PAPER_TYPE tag can be used to set the paper type that is used 

+# by the printer. Possible values are: a4, a4wide, letter, legal and 

+# executive. If left blank a4wide will be used.

+

+PAPER_TYPE             = a4wide

+

+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 

+# packages that should be included in the LaTeX output.

+

+EXTRA_PACKAGES         = 

+

+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 

+# the generated latex document. The header should contain everything until 

+# the first chapter. If it is left blank doxygen will generate a 

+# standard header. Notice: only use this tag if you know what you are doing!

+

+LATEX_HEADER           = 

+

+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 

+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 

+# contain links (just like the HTML output) instead of page references 

+# This makes the output suitable for online browsing using a pdf viewer.

+

+PDF_HYPERLINKS         = YES

+

+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 

+# plain latex in the generated Makefile. Set this option to YES to get a 

+# higher quality PDF documentation.

+

+USE_PDFLATEX           = YES

+

+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 

+# command to the generated LaTeX files. This will instruct LaTeX to keep 

+# running if errors occur, instead of asking the user for help. 

+# This option is also used when generating formulas in HTML.

+

+LATEX_BATCHMODE        = NO

+

+#---------------------------------------------------------------------------

+# configuration options related to the RTF output

+#---------------------------------------------------------------------------

+

+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 

+# The RTF output is optimised for Word 97 and may not look very pretty with 

+# other RTF readers or editors.

+

+GENERATE_RTF           = NO

+

+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 

+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 

+# put in front of it. If left blank `rtf' will be used as the default path.

+

+RTF_OUTPUT             = rtf

+

+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 

+# RTF documents. This may be useful for small projects and may help to 

+# save some trees in general.

+

+COMPACT_RTF            = NO

+

+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 

+# will contain hyperlink fields. The RTF file will 

+# contain links (just like the HTML output) instead of page references. 

+# This makes the output suitable for online browsing using WORD or other 

+# programs which support those fields. 

+# Note: wordpad (write) and others do not support links.

+

+RTF_HYPERLINKS         = NO

+

+# Load stylesheet definitions from file. Syntax is similar to doxygen's 

+# config file, i.e. a series of assigments. You only have to provide 

+# replacements, missing definitions are set to their default value.

+

+RTF_STYLESHEET_FILE    = 

+

+# Set optional variables used in the generation of an rtf document. 

+# Syntax is similar to doxygen's config file.

+

+RTF_EXTENSIONS_FILE    = 

+

+#---------------------------------------------------------------------------

+# configuration options related to the man page output

+#---------------------------------------------------------------------------

+

+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 

+# generate man pages

+

+GENERATE_MAN           = NO

+

+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 

+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 

+# put in front of it. If left blank `man' will be used as the default path.

+

+MAN_OUTPUT             = man

+

+# The MAN_EXTENSION tag determines the extension that is added to 

+# the generated man pages (default is the subroutine's section .3)

+

+MAN_EXTENSION          = .3

+

+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 

+# then it will generate one additional man file for each entity 

+# documented in the real man page(s). These additional files 

+# only source the real man page, but without them the man command 

+# would be unable to find the correct page. The default is NO.

+

+MAN_LINKS              = NO

+

+#---------------------------------------------------------------------------

+# configuration options related to the XML output

+#---------------------------------------------------------------------------

+

+# If the GENERATE_XML tag is set to YES Doxygen will 

+# generate an XML file that captures the structure of 

+# the code including all documentation. Note that this 

+# feature is still experimental and incomplete at the 

+# moment.

+

+GENERATE_XML           = NO

+

+# The XML_SCHEMA tag can be used to specify an XML schema, 

+# which can be used by a validating XML parser to check the 

+# syntax of the XML files.

+

+XML_SCHEMA             = 

+

+# The XML_DTD tag can be used to specify an XML DTD, 

+# which can be used by a validating XML parser to check the 

+# syntax of the XML files.

+

+XML_DTD                = 

+

+#---------------------------------------------------------------------------

+# configuration options for the AutoGen Definitions output

+#---------------------------------------------------------------------------

+

+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 

+# generate an AutoGen Definitions (see autogen.sf.net) file 

+# that captures the structure of the code including all 

+# documentation. Note that this feature is still experimental 

+# and incomplete at the moment.

+

+GENERATE_AUTOGEN_DEF   = NO

+

+#---------------------------------------------------------------------------

+# configuration options related to the Perl module output

+#---------------------------------------------------------------------------

+

+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 

+# generate a Perl module file that captures the structure of 

+# the code including all documentation. Note that this 

+# feature is still experimental and incomplete at the 

+# moment.

+

+GENERATE_PERLMOD       = NO

+

+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 

+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 

+# to generate PDF and DVI output from the Perl module output.

+

+PERLMOD_LATEX          = NO

+

+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 

+# nicely formatted so it can be parsed by a human reader.  This is useful 

+# if you want to understand what is going on.  On the other hand, if this 

+# tag is set to NO the size of the Perl module output will be much smaller 

+# and Perl will parse it just the same.

+

+PERLMOD_PRETTY         = YES

+

+# The names of the make variables in the generated doxyrules.make file 

+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 

+# This is useful so different doxyrules.make files included by the same 

+# Makefile don't overwrite each other's variables.

+

+PERLMOD_MAKEVAR_PREFIX = 

+

+#---------------------------------------------------------------------------

+# Configuration options related to the preprocessor   

+#---------------------------------------------------------------------------

+

+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 

+# evaluate all C-preprocessor directives found in the sources and include 

+# files.

+

+ENABLE_PREPROCESSING   = YES

+

+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 

+# names in the source code. If set to NO (the default) only conditional 

+# compilation will be performed. Macro expansion can be done in a controlled 

+# way by setting EXPAND_ONLY_PREDEF to YES.

+

+MACRO_EXPANSION        = YES

+

+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 

+# then the macro expansion is limited to the macros specified with the 

+# PREDEFINED and EXPAND_AS_PREDEFINED tags.

+

+EXPAND_ONLY_PREDEF     = NO

+

+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 

+# in the INCLUDE_PATH (see below) will be search if a #include is found.

+

+SEARCH_INCLUDES        = YES

+

+# The INCLUDE_PATH tag can be used to specify one or more directories that 

+# contain include files that are not input files but should be processed by 

+# the preprocessor.

+

+INCLUDE_PATH           = 

+

+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 

+# patterns (like *.h and *.hpp) to filter out the header-files in the 

+# directories. If left blank, the patterns specified with FILE_PATTERNS will 

+# be used.

+

+INCLUDE_FILE_PATTERNS  = 

+

+# The PREDEFINED tag can be used to specify one or more macro names that 

+# are defined before the preprocessor is started (similar to the -D option of 

+# gcc). The argument of the tag is a list of macros of the form: name 

+# or name=definition (no spaces). If the definition and the = are 

+# omitted =1 is assumed.

+

+PREDEFINED             = PJ_DECL(x)=x PJ_DEF(x)=x PJ_IDECL(x)=x \

+			 PJ_IDEF(x)=x PJ_INLINE(x)=x \

+			 PJ_DECL_NO_RETURN(x)=x \

+			 PJ_HAS_HIGH_RES_TIMER=1 \

+			 PJ_LOG_MAX_LEVEL=4 \

+			 PJ_HAS_SEMAPHORE=1 \

+			 PJ_HAS_EVENT_OBJ=1

+

+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 

+# this tag can be used to specify a list of macro names that should be expanded. 

+# The macro definition that is found in the sources will be used. 

+# Use the PREDEFINED tag if you want to use a different macro definition.

+

+EXPAND_AS_DEFINED      = 

+

+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 

+# doxygen's preprocessor will remove all function-like macros that are alone 

+# on a line, have an all uppercase name, and do not end with a semicolon. Such 

+# function macros are typically used for boiler-plate code, and will confuse the 

+# parser if not removed.

+

+SKIP_FUNCTION_MACROS   = YES

+

+#---------------------------------------------------------------------------

+# Configuration::addtions related to external references   

+#---------------------------------------------------------------------------

+

+# The TAGFILES tag can be used to specify one or more tagfiles.

+

+TAGFILES               = ../pjlib/docs/pjlib.tag=../../../pjlib/docs/html ../pjlib-util/docs/pjlib-util.tag=../../../pjlib-util/docs/html ../pjsip/docs/pjsip.tag=../../../pjsip/docs/html ../pjmedia/docs/pjmedia.tag=../../../pjmedia/docs/html

+

+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 

+# a tag file that is based on the input files it reads.

+

+GENERATE_TAGFILE       = ../pjnath/docs/pjnath.tag

+

+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 

+# in the class index. If set to NO only the inherited external classes 

+# will be listed.

+

+ALLEXTERNALS           = NO

+

+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 

+# in the modules index. If set to NO, only the current project's groups will 

+# be listed.

+

+EXTERNAL_GROUPS        = NO

+

+# The PERL_PATH should be the absolute path and name of the perl script 

+# interpreter (i.e. the result of `which perl').

+

+#PERL_PATH              = /usr/bin/perl

+PERL_PATH              = /c/Perl/bin/perl

+

+#---------------------------------------------------------------------------

+# Configuration options related to the dot tool   

+#---------------------------------------------------------------------------

+

+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 

+# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or 

+# super classes. Setting the tag to NO turns the diagrams off. Note that this 

+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is 

+# recommended to install and use dot, since it yield more powerful graphs.

+

+CLASS_DIAGRAMS         = NO

+

+# If set to YES, the inheritance and collaboration graphs will hide 

+# inheritance and usage relations if the target is undocumented 

+# or is not a class.

+

+HIDE_UNDOC_RELATIONS   = YES

+

+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 

+# available from the path. This tool is part of Graphviz, a graph visualization 

+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 

+# have no effect if this option is set to NO (the default)

+

+HAVE_DOT               = NO

+

+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 

+# will generate a graph for each documented class showing the direct and 

+# indirect inheritance relations. Setting this tag to YES will force the 

+# the CLASS_DIAGRAMS tag to NO.

+

+CLASS_GRAPH            = YES

+

+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 

+# will generate a graph for each documented class showing the direct and 

+# indirect implementation dependencies (inheritance, containment, and 

+# class references variables) of the class with other documented classes.

+

+COLLABORATION_GRAPH    = YES

+

+# If set to YES, the inheritance and collaboration graphs will show the 

+# relations between templates and their instances.

+

+TEMPLATE_RELATIONS     = YES

+

+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 

+# tags are set to YES then doxygen will generate a graph for each documented 

+# file showing the direct and indirect include dependencies of the file with 

+# other documented files.

+

+INCLUDE_GRAPH          = YES

+

+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 

+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 

+# documented header file showing the documented files that directly or 

+# indirectly include this file.

+

+INCLUDED_BY_GRAPH      = YES

+

+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 

+# will graphical hierarchy of all classes instead of a textual one.

+

+GRAPHICAL_HIERARCHY    = YES

+

+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 

+# generated by dot. Possible values are png, jpg, or gif

+# If left blank png will be used.

+

+DOT_IMAGE_FORMAT       = png

+

+# The tag DOT_PATH can be used to specify the path where the dot tool can be 

+# found. If left blank, it is assumed the dot tool can be found on the path.

+

+DOT_PATH               = 

+

+# The DOTFILE_DIRS tag can be used to specify one or more directories that 

+# contain dot files that are included in the documentation (see the 

+# \dotfile command).

+

+DOTFILE_DIRS           = 

+

+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 

+# generate a legend page explaining the meaning of the various boxes and 

+# arrows in the dot generated graphs.

+

+GENERATE_LEGEND        = YES

+

+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 

+# remove the intermedate dot files that are used to generate 

+# the various graphs.

+

+DOT_CLEANUP            = YES

+

+#---------------------------------------------------------------------------

+# Configuration::addtions related to the search engine   

+#---------------------------------------------------------------------------

+

+# The SEARCHENGINE tag specifies whether or not a search engine should be 

+# used. If set to NO the values of all tags below this one will be ignored.

+

+SEARCHENGINE           = NO

+

+# The CGI_NAME tag should be the name of the CGI script that 

+# starts the search engine (doxysearch) with the correct parameters. 

+# A script with this name will be generated by doxygen.

+

+#CGI_NAME               = search.cgi

+

+# The CGI_URL tag should be the absolute URL to the directory where the 

+# cgi binaries are located. See the documentation of your http daemon for 

+# details.

+

+#CGI_URL                = 

+

+# The DOC_URL tag should be the absolute URL to the directory where the 

+# documentation is located. If left blank the absolute path to the 

+# documentation, with file:// prepended to it, will be used.

+

+#DOC_URL                = 

+

+# The DOC_ABSPATH tag should be the absolute path to the directory where the 

+# documentation is located. If left blank the directory on the local machine 

+# will be used.

+

+#DOC_ABSPATH            = 

+

+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary 

+# is installed.

+

+#BIN_ABSPATH            = /usr/local/bin/

+

+# The EXT_DOC_PATHS tag can be used to specify one or more paths to 

+# documentation generated for other projects. This allows doxysearch to search 

+# the documentation for these projects as well.

+

+#EXT_DOC_PATHS          = 

diff --git a/jni/pjproject-android/.svn/pristine/f1/f19c90785b4afe174feff5747d7d650037830992.svn-base b/jni/pjproject-android/.svn/pristine/f1/f19c90785b4afe174feff5747d7d650037830992.svn-base
new file mode 100644
index 0000000..309459b
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f1/f19c90785b4afe174feff5747d7d650037830992.svn-base
@@ -0,0 +1,349 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <pj/pool.h>
+#include "test.h"
+
+#define JB_INIT_PREFETCH    0
+#define JB_MIN_PREFETCH	    0
+#define JB_MAX_PREFETCH	    10
+#define JB_PTIME	    20
+#define JB_BUF_SIZE	    50
+
+//#define REPORT
+//#define PRINT_COMMENT
+
+typedef struct test_param_t {
+    pj_bool_t adaptive;
+    unsigned init_prefetch;
+    unsigned min_prefetch;
+    unsigned max_prefetch;
+} test_param_t;
+
+typedef struct test_cond_t {
+    int burst;
+    int discard;
+    int lost;
+    int empty;
+    int delay;	    /**< Average delay, in frames.	    */
+    int delay_min;  /**< Minimum delay, in frames.	    */
+} test_cond_t;
+
+static pj_bool_t parse_test_headers(char *line, test_param_t *param, 
+			       test_cond_t *cond)
+{
+    char *p = line;
+
+    if (*p == '%') {
+	/* Test params. */
+	char mode_st[16];
+
+	sscanf(p+1, "%s %u %u %u", mode_st, &param->init_prefetch, 
+	       &param->min_prefetch, &param->max_prefetch);
+	param->adaptive = (pj_ansi_stricmp(mode_st, "adaptive") == 0);
+
+    } else if (*p == '!') {
+	/* Success condition. */
+	char cond_st[16];
+	unsigned cond_val;
+
+	sscanf(p+1, "%s %u", cond_st, &cond_val);
+	if (pj_ansi_stricmp(cond_st, "burst") == 0)
+	    cond->burst = cond_val;
+	else if (pj_ansi_stricmp(cond_st, "delay") == 0)
+	    cond->delay = cond_val;
+	else if (pj_ansi_stricmp(cond_st, "delay_min") == 0)
+	    cond->delay_min = cond_val;
+	else if (pj_ansi_stricmp(cond_st, "discard") == 0)
+	    cond->discard = cond_val;
+	else if (pj_ansi_stricmp(cond_st, "empty") == 0)
+	    cond->empty = cond_val;
+	else if (pj_ansi_stricmp(cond_st, "lost") == 0)
+	    cond->lost = cond_val;
+
+    } else if (*p == '=') {
+	/* Test title. */
+	++p;
+	while (*p && isspace(*p)) ++p;
+	printf("%s", p);
+
+    } else if (*p == '#') {
+	/* Ignore comment line. */
+
+    } else {
+	/* Unknown header, perhaps this is the test data */
+
+	/* Skip spaces */
+	while (*p && isspace(*p)) ++p;
+
+	/* Test data started.*/
+	if (*p != 0)
+	    return PJ_FALSE;
+    }
+
+    return PJ_TRUE;
+}
+
+static pj_bool_t process_test_data(char data, pjmedia_jbuf *jb, 
+				   pj_uint16_t *seq, pj_uint16_t *last_seq)
+{
+    char frame[1];
+    char f_type;
+    pj_bool_t print_state = PJ_TRUE;
+    pj_bool_t data_eos = PJ_FALSE;
+
+    switch (toupper(data)) {
+    case 'G': /* Get */
+	pjmedia_jbuf_get_frame(jb, frame, &f_type);
+	break;
+    case 'P': /* Put */
+	pjmedia_jbuf_put_frame(jb, (void*)frame, 1, *seq);
+	*last_seq = *seq;
+	++*seq;
+	break;
+    case 'L': /* Lost */
+	*last_seq = *seq;
+	++*seq;
+	printf("Lost\n");
+	break;
+    case 'R': /* Sequence restarts */
+	*seq = 1;
+	printf("Sequence restarting, from %u to %u\n", *last_seq, *seq);
+	break;
+    case 'J': /* Sequence jumps */
+	(*seq) += 20;
+	printf("Sequence jumping, from %u to %u\n", *last_seq, *seq);
+	break;
+    case 'D': /* Frame duplicated */
+	pjmedia_jbuf_put_frame(jb, (void*)frame, 1, *seq - 1);
+	break;
+    case 'O': /* Old/late frame */
+	pjmedia_jbuf_put_frame(jb, (void*)frame, 1, *seq - 10 - pj_rand()%40);
+	break;
+    case '.': /* End of test session. */
+	data_eos = PJ_TRUE;
+	break;
+    default:
+	print_state = PJ_FALSE;
+	printf("Unknown test data '%c'\n", data);
+	break;
+    }
+
+    if (data_eos)
+	return PJ_FALSE;
+
+#ifdef REPORT
+    if (print_state) {
+	pjmedia_jb_state state;
+
+	pjmedia_jbuf_get_state(jb, &state);
+	printf("seq=%d\t%c\tsize=%d\tprefetch=%d\n", 
+	       *last_seq, toupper(data), state.size, state.prefetch);
+    }
+#endif
+
+    return PJ_TRUE;
+}
+
+int jbuf_main(void)
+{
+    FILE *input;
+    pj_bool_t data_eof = PJ_FALSE;
+    int old_log_level;
+    int rc = 0;
+    const char* input_filename = "Jbtest.dat";
+    const char* input_search_path[] = { 
+	"../build",
+	"pjmedia/build",
+	"build"
+    };
+
+    /* Try to open test data file in the working directory */
+    input = fopen(input_filename, "rt");
+
+    /* If that fails, try to open test data file in specified search paths */
+    if (input == NULL) {
+	char input_path[PJ_MAXPATH];
+	int i;
+
+	for (i = 0; !input && i < PJ_ARRAY_SIZE(input_search_path); ++i) {
+	    pj_ansi_snprintf(input_path, PJ_MAXPATH, "%s/%s",
+			     input_search_path[i],
+			     input_filename);
+	    input = fopen(input_path, "rt");
+	}
+    }
+    
+    /* Failed to open test data file. */
+    if (input == NULL) {
+	printf("Failed to open test data file, Jbtest.dat\n");
+	return -1;
+    }
+
+    old_log_level = pj_log_get_level();
+    pj_log_set_level(5);
+
+    while (rc == 0 && !data_eof) {
+	pj_str_t jb_name = {"JBTEST", 6};
+	pjmedia_jbuf *jb;
+	pj_pool_t *pool;
+	pjmedia_jb_state state;
+	pj_uint16_t last_seq = 0;
+	pj_uint16_t seq = 1;
+	char line[1024], *p = NULL;
+
+	test_param_t param;
+	test_cond_t cond;
+
+	param.adaptive = PJ_TRUE;
+	param.init_prefetch = JB_INIT_PREFETCH;
+	param.min_prefetch = JB_MIN_PREFETCH;
+	param.max_prefetch = JB_MAX_PREFETCH;
+
+	cond.burst = -1;
+	cond.delay = -1;
+	cond.delay_min = -1;
+	cond.discard = -1;
+	cond.empty = -1;
+	cond.lost = -1;
+
+	printf("\n\n");
+
+	/* Parse test session title, param, and conditions */
+	do {
+	    p = fgets(line, sizeof(line), input);
+	} while (p && parse_test_headers(line, &param, &cond));
+
+	/* EOF test data */
+	if (p == NULL)
+	    break;
+
+	//printf("======================================================\n");
+
+	/* Initialize test session */
+	pool = pj_pool_create(mem, "JBPOOL", 256*16, 256*16, NULL);
+	pjmedia_jbuf_create(pool, &jb_name, 1, JB_PTIME, JB_BUF_SIZE, &jb);
+	pjmedia_jbuf_reset(jb);
+
+	if (param.adaptive) {
+	    pjmedia_jbuf_set_adaptive(jb, 
+				      param.init_prefetch, 
+				      param.min_prefetch,
+				      param.max_prefetch);
+	} else {
+	    pjmedia_jbuf_set_fixed(jb, param.init_prefetch);
+	}
+
+#ifdef REPORT
+	pjmedia_jbuf_get_state(jb, &state);
+	printf("Initial\tsize=%d\tprefetch=%d\tmin.pftch=%d\tmax.pftch=%d\n", 
+	       state.size, state.prefetch, state.min_prefetch, 
+	       state.max_prefetch);
+#endif
+
+
+	/* Test session start */
+	while (1) {
+	    char c;
+	    
+	    /* Get next line of test data */
+	    if (!p || *p == 0) {
+		p = fgets(line, sizeof(line), input);
+		if (p == NULL) {
+		    data_eof = PJ_TRUE;
+		    break;
+		}
+	    }
+
+	    /* Get next char of test data */
+	    c = *p++;
+
+	    /* Skip spaces */
+	    if (isspace(c))
+		continue;
+
+	    /* Print comment line */
+	    if (c == '#') {
+#ifdef PRINT_COMMENT
+		while (*p && isspace(*p)) ++p;
+		if (*p) printf("..%s", p);
+#endif
+		*p = 0;
+		continue;
+	    }
+
+	    /* Process test data */
+	    if (!process_test_data(c, jb, &seq, &last_seq))
+		break;
+	}
+
+	/* Print JB states */
+	pjmedia_jbuf_get_state(jb, &state);
+	printf("------------------------------------------------------\n");
+	printf("Summary:\n");
+	printf("  size=%d prefetch=%d\n", state.size, state.prefetch);
+	printf("  delay (min/max/avg/dev)=%d/%d/%d/%d ms\n",
+	       state.min_delay, state.max_delay, state.avg_delay, 
+	       state.dev_delay);
+	printf("  lost=%d discard=%d empty=%d burst(avg)=%d\n", 
+	       state.lost, state.discard, state.empty, state.avg_burst);
+
+	/* Evaluate test session */
+	if (cond.burst >= 0 && (int)state.avg_burst > cond.burst) {
+	    printf("! 'Burst' should be %d, it is %d\n", 
+		   cond.burst, state.avg_burst);
+	    rc |= 1;
+	}
+	if (cond.delay >= 0 && (int)state.avg_delay/JB_PTIME > cond.delay) {
+	    printf("! 'Delay' should be %d, it is %d\n", 
+		   cond.delay, state.avg_delay/JB_PTIME);
+	    rc |= 2;
+	}
+	if (cond.delay_min >= 0 && (int)state.min_delay/JB_PTIME > cond.delay_min) {
+	    printf("! 'Minimum delay' should be %d, it is %d\n", 
+		   cond.delay_min, state.min_delay/JB_PTIME);
+	    rc |= 32;
+	}
+	if (cond.discard >= 0 && (int)state.discard > cond.discard) {
+	    printf("! 'Discard' should be %d, it is %d\n",
+		   cond.discard, state.discard);
+	    rc |= 4;
+	}
+	if (cond.empty >= 0 && (int)state.empty > cond.empty) {
+	    printf("! 'Empty' should be %d, it is %d\n", 
+		   cond.empty, state.empty);
+	    rc |= 8;
+	}
+	if (cond.lost >= 0 && (int)state.lost > cond.lost) {
+	    printf("! 'Lost' should be %d, it is %d\n", 
+		   cond.lost, state.lost);
+	    rc |= 16;
+	}
+
+	pjmedia_jbuf_destroy(jb);
+	pj_pool_release(pool);
+    }
+
+    fclose(input);
+    pj_log_set_level(old_log_level);
+
+    return rc;
+}
diff --git a/jni/pjproject-android/.svn/pristine/f1/f1b629c31cb2499d2884f6defd74e077800602dc.svn-base b/jni/pjproject-android/.svn/pristine/f1/f1b629c31cb2499d2884f6defd74e077800602dc.svn-base
new file mode 100644
index 0000000..189eb00
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f1/f1b629c31cb2499d2884f6defd74e077800602dc.svn-base
@@ -0,0 +1,21 @@
+#Modify this to point to the PJSIP location.
+PJBASE=~/Desktop/project/pjproject
+
+include $(PJBASE)/build.mak
+
+CC      = $(APP_CC)
+LDFLAGS = $(APP_LDFLAGS)
+LDLIBS  = $(APP_LDLIBS)
+CFLAGS  = $(APP_CFLAGS)
+CPPFLAGS= ${CFLAGS}
+
+# If your application is in a file named myapp.cpp or myapp.c
+# # this is the line you will need to build the binary.
+# all: myapp
+#
+cmp_wav: cmp_wav.c
+	$(CC) -o $@ $< $(CPPFLAGS) $(LDFLAGS) $(LDLIBS)
+
+clean:
+	rm -f cmp_wav.o cmp_wav
+
diff --git a/jni/pjproject-android/.svn/pristine/f1/f1d1d45e09f609a4afb70fce26c077cf2fd3d93b.svn-base b/jni/pjproject-android/.svn/pristine/f1/f1d1d45e09f609a4afb70fce26c077cf2fd3d93b.svn-base
new file mode 100644
index 0000000..a80cfeb
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f1/f1d1d45e09f609a4afb70fce26c077cf2fd3d93b.svn-base
@@ -0,0 +1,33 @@
+TARGET 		pjmedia_audiodev.lib
+TARGETTYPE 	lib
+
+SOURCEPATH	..\pjmedia\src\pjmedia-audiodev
+
+//
+// GCCE optimization setting
+//
+//OPTION		GCCE -O2 -fno-unit-at-a-time
+OPTION          ARMCC --gnu
+
+MACRO		PJ_M_I386=1
+MACRO		PJ_SYMBIAN=1
+
+SOURCE		audiodev.c
+SOURCE		errno.c
+SOURCE		symb_aps_dev.cpp
+SOURCE		symb_mda_dev.cpp
+SOURCE		symb_vas_dev.cpp
+SOURCE		null_dev.c
+
+SYSTEMINCLUDE	..\pjmedia\include
+SYSTEMINCLUDE	..\pjlib\include 
+SYSTEMINCLUDE	..\pjlib-util\include 
+
+SYSTEMINCLUDE	\epoc32\include
+SYSTEMINCLUDE	\epoc32\include\libc
+SYSTEMINCLUDE   \epoc32\include\mmf\server 
+SYSTEMINCLUDE   \epoc32\include\mmf\common 
+SYSTEMINCLUDE   \epoc32\include\mda\common 
+SYSTEMINCLUDE	\epoc32\include\mmf\plugin 
+
+
diff --git a/jni/pjproject-android/.svn/pristine/f1/f1f60ed301d8cac478d341dca0b456d789a398f1.svn-base b/jni/pjproject-android/.svn/pristine/f1/f1f60ed301d8cac478d341dca0b456d789a398f1.svn-base
new file mode 100644
index 0000000..eb0e390
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/f1/f1f60ed301d8cac478d341dca0b456d789a398f1.svn-base
@@ -0,0 +1,78 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+/*
+ * Based on implementation found in Carnegie Mellon Speech Group Software
+ * depository (ftp://ftp.cs.cmu.edu/project/fgdata/index.html). No copyright
+ * was claimed in the original source codes.
+ */
+#ifndef __PJMEDIA_CODEC_G722_ENC_H__
+#define __PJMEDIA_CODEC_G722_ENC_H__
+
+#include <pjmedia-codec/types.h>
+
+/* Encoder state */
+typedef struct g722_enc_t {
+    /* PCM low band */
+    int slow;
+    int detlow;
+    int spl;
+    int szl;
+    int rlt  [3];
+    int al   [3];
+    int apl  [3];
+    int plt  [3];
+    int dlt  [7];
+    int bl   [7];
+    int bpl  [7];
+    int sgl  [7];
+    int nbl;
+
+    /* PCM high band*/
+    int shigh;
+    int dethigh;
+    int sph;
+    int szh;
+    int rh   [3];
+    int ah   [3];
+    int aph  [3];
+    int ph   [3];
+    int dh   [7];
+    int bh   [7];
+    int bph  [7];
+    int sgh  [7];
+    int nbh;
+
+    /* QMF signal history */
+    int x[24];
+} g722_enc_t;
+
+
+PJ_DECL(pj_status_t) g722_enc_init(g722_enc_t *enc);
+
+PJ_DECL(pj_status_t) g722_enc_encode(g722_enc_t *enc, 
+				     pj_int16_t in[], 
+				     pj_size_t nsamples,
+				     void *out,
+				     pj_size_t *out_size);
+
+PJ_DECL(pj_status_t) g722_enc_deinit(g722_enc_t *enc);
+
+#endif /* __PJMEDIA_CODEC_G722_ENC_H__ */
+