* #36737: switch back to svn repo, remove assert in sip_transaction.c
diff --git a/jni/pjproject-android/.svn/pristine/c6/c65b96490fde338b95524ddb7c9703cfb504c58e.svn-base b/jni/pjproject-android/.svn/pristine/c6/c65b96490fde338b95524ddb7c9703cfb504c58e.svn-base
new file mode 100644
index 0000000..30a81f9
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c6/c65b96490fde338b95524ddb7c9703cfb504c58e.svn-base
@@ -0,0 +1,46 @@
+#
+# PJLIB OS specific configuration for RTEMS
+#
+# Thanks Zetron, Inc. and Phil Torre <ptorre@zetron.com> for donating PJLIB
+# port to RTEMS.
+#
+
+#
+# PJLIB_OBJS specified here are object files to be included in PJLIB
+# (the library) for this specific operating system. Object files common
+# to all operating systems should go in Makefile instead.
+#
+export PJLIB_OBJS += addr_resolv_sock.o guid_simple.o \
+ log_writer_stdout.o os_core_unix.o \
+ os_error_unix.o os_time_unix.o \
+ os_timestamp_common.o os_timestamp_posix.o \
+ pool_policy_malloc.o sock_bsd.o sock_select.o
+
+export PJLIB_OBJS += ioqueue_select.o
+export PJLIB_OBJS += file_access_unistd.o file_io_ansi.o
+
+#
+# TEST_OBJS are operating system specific object files to be included in
+# the test application.
+#
+export TEST_OBJS += main_rtems.o
+
+#
+# RTEMS_LIBRARY_PATH points to the installed RTEMS libraries for the
+# desired target. pjlib-test can't link without this.
+#
+export RTEMS_LIBRARY_PATH := $(RTEMS_LIBRARY_PATH)
+
+#
+# Additional LDFLAGS for pjlib-test
+#
+export TEST_LDFLAGS +=
+
+#
+# TARGETS are make targets in the Makefile, to be executed for this given
+# operating system.
+#
+export TARGETS = $(PJLIB_LIB) $(TEST_EXE)
+
+
+
diff --git a/jni/pjproject-android/.svn/pristine/c6/c673b982c35f1fe6341a02a3f276284010fc856b.svn-base b/jni/pjproject-android/.svn/pristine/c6/c673b982c35f1fe6341a02a3f276284010fc856b.svn-base
new file mode 100644
index 0000000..552a6fb
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c6/c673b982c35f1fe6341a02a3f276284010fc856b.svn-base
@@ -0,0 +1,807 @@
+/* $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/splitcomb.h>
+#include <pjmedia/delaybuf.h>
+#include <pjmedia/errno.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+#include <pj/pool.h>
+
+
+#define SIGNATURE PJMEDIA_SIG_PORT_SPLIT_COMB
+#define SIGNATURE_PORT PJMEDIA_SIG_PORT_SPLIT_COMB_P
+#define THIS_FILE "splitcomb.c"
+#define TMP_SAMP_TYPE pj_int16_t
+
+/* Maximum number of channels. */
+#define MAX_CHANNELS 16
+
+/* Maximum number of buffers to be accommodated by delaybuf */
+#define MAX_BUF_CNT PJMEDIA_SOUND_BUFFER_COUNT
+
+/* Maximum number of burst before we pause the media flow */
+#define MAX_BURST (buf_cnt + 6)
+
+/* Maximum number of NULL frames received before we pause the
+ * media flow.
+ */
+#define MAX_NULL_FRAMES (rport->max_burst)
+
+
+/* Operations */
+#define OP_PUT (1)
+#define OP_GET (-1)
+
+
+/*
+ * Media flow directions:
+ *
+ * put_frame() +-----+
+ * UPSTREAM ------------>|split|<--> DOWNSTREAM
+ * <------------|comb |
+ * get_frame() +-----+
+ *
+ */
+enum sc_dir
+{
+ /* This is the media direction from the splitcomb to the
+ * downstream port(s), which happens when:
+ * - put_frame() is called to the splitcomb
+ * - get_frame() is called to the reverse channel port.
+ */
+ DIR_DOWNSTREAM,
+
+ /* This is the media direction from the downstream port to
+ * the splitcomb, which happens when:
+ * - get_frame() is called to the splitcomb
+ * - put_frame() is called to the reverse channel port.
+ */
+ DIR_UPSTREAM
+};
+
+
+
+/*
+ * This structure describes the splitter/combiner.
+ */
+struct splitcomb
+{
+ pjmedia_port base;
+
+ unsigned options;
+
+ /* Array of ports, one for each channel */
+ struct {
+ pjmedia_port *port;
+ pj_bool_t reversed;
+ } port_desc[MAX_CHANNELS];
+
+ /* Temporary buffers needed to extract mono frame from
+ * multichannel frame. We could use stack for this, but this
+ * way it should be safer for devices with small stack size.
+ */
+ TMP_SAMP_TYPE *get_buf;
+ TMP_SAMP_TYPE *put_buf;
+};
+
+
+/*
+ * This structure describes reverse port.
+ */
+struct reverse_port
+{
+ pjmedia_port base;
+ struct splitcomb*parent;
+ unsigned ch_num;
+
+ /* Maximum burst before media flow is suspended.
+ * With reverse port, it's possible that either end of the
+ * port doesn't actually process the media flow (meaning, it
+ * stops calling get_frame()/put_frame()). When this happens,
+ * the other end will encounter excessive underflow or overflow,
+ * depending on which direction is not actively processed by
+ * the stopping end.
+ *
+ * To avoid excessive underflow/overflow, the media flow will
+ * be suspended once underflow/overflow goes over this max_burst
+ * limit.
+ */
+ int max_burst;
+
+ /* When the media interface port of the splitcomb or the reverse
+ * channel port is registered to conference bridge, the bridge
+ * will transmit NULL frames to the media port when the media
+ * port is not receiving any audio from other slots (for example,
+ * when no other slots are connected to the media port).
+ *
+ * When this happens, we will generate zero frame to our buffer,
+ * to avoid underflow/overflow. But after too many NULL frames
+ * are received, we will pause the media flow instead, to save
+ * some processing.
+ *
+ * This value controls how many NULL frames can be received
+ * before we suspend media flow for a particular direction.
+ */
+ unsigned max_null_frames;
+
+ /* A reverse port need a temporary buffer to store frames
+ * (because of the different phase, see splitcomb.h for details).
+ * Since we can not expect get_frame() and put_frame() to be
+ * called evenly one after another, we use delay buffers to
+ * accomodate the burst.
+ *
+ * We maintain state for each direction, hence the array. The
+ * array is indexed by direction (sc_dir).
+ */
+ struct {
+
+ /* The delay buffer where frames will be stored */
+ pjmedia_delay_buf *dbuf;
+
+ /* Flag to indicate that audio flow on this direction
+ * is currently being suspended (perhaps because nothing
+ * is processing the frame on the other end).
+ */
+ pj_bool_t paused;
+
+ /* Operation level. When the level exceeds a maximum value,
+ * the media flow on this direction will be paused.
+ */
+ int level;
+
+ /* Timestamp. */
+ pj_timestamp ts;
+
+ /* Number of NULL frames transmitted to this port so far.
+ * NULL frame indicate that nothing is transmitted, and
+ * once we get too many of this, we should pause the media
+ * flow to reduce processing.
+ */
+ unsigned null_cnt;
+
+ } buf[2];
+
+ /* Must have temporary put buffer for the delay buf,
+ * unfortunately.
+ */
+ pj_int16_t *tmp_up_buf;
+};
+
+
+/*
+ * 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 on_destroy(pjmedia_port *this_port);
+
+static pj_status_t rport_put_frame(pjmedia_port *this_port,
+ pjmedia_frame *frame);
+static pj_status_t rport_get_frame(pjmedia_port *this_port,
+ pjmedia_frame *frame);
+static pj_status_t rport_on_destroy(pjmedia_port *this_port);
+
+
+/*
+ * Create the splitter/combiner.
+ */
+PJ_DEF(pj_status_t) pjmedia_splitcomb_create( pj_pool_t *pool,
+ unsigned clock_rate,
+ unsigned channel_count,
+ unsigned samples_per_frame,
+ unsigned bits_per_sample,
+ unsigned options,
+ pjmedia_port **p_splitcomb)
+{
+ const pj_str_t name = pj_str("splitcomb");
+ struct splitcomb *sc;
+
+ /* Sanity check */
+ PJ_ASSERT_RETURN(pool && clock_rate && channel_count &&
+ samples_per_frame && bits_per_sample &&
+ p_splitcomb, PJ_EINVAL);
+
+ /* Only supports 16 bits per sample */
+ PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);
+
+ *p_splitcomb = NULL;
+
+ /* Create the splitter/combiner structure */
+ sc = PJ_POOL_ZALLOC_T(pool, struct splitcomb);
+ PJ_ASSERT_RETURN(sc != NULL, PJ_ENOMEM);
+
+ /* Create temporary buffers */
+ sc->get_buf = (TMP_SAMP_TYPE*)
+ pj_pool_alloc(pool, samples_per_frame *
+ sizeof(TMP_SAMP_TYPE) /
+ channel_count);
+ PJ_ASSERT_RETURN(sc->get_buf, PJ_ENOMEM);
+
+ sc->put_buf = (TMP_SAMP_TYPE*)
+ pj_pool_alloc(pool, samples_per_frame *
+ sizeof(TMP_SAMP_TYPE) /
+ channel_count);
+ PJ_ASSERT_RETURN(sc->put_buf, PJ_ENOMEM);
+
+
+ /* Save options */
+ sc->options = options;
+
+ /* Initialize port */
+ pjmedia_port_info_init(&sc->base.info, &name, SIGNATURE, clock_rate,
+ channel_count, bits_per_sample, samples_per_frame);
+
+ sc->base.put_frame = &put_frame;
+ sc->base.get_frame = &get_frame;
+ sc->base.on_destroy = &on_destroy;
+
+ /* Init ports array */
+ /*
+ sc->port_desc = pj_pool_zalloc(pool, channel_count*sizeof(*sc->port_desc));
+ */
+ pj_bzero(sc->port_desc, sizeof(sc->port_desc));
+
+ /* Done for now */
+ *p_splitcomb = &sc->base;
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Attach media port with the same phase as the splitter/combiner.
+ */
+PJ_DEF(pj_status_t) pjmedia_splitcomb_set_channel( pjmedia_port *splitcomb,
+ unsigned ch_num,
+ unsigned options,
+ pjmedia_port *port)
+{
+ struct splitcomb *sc = (struct splitcomb*) splitcomb;
+
+ /* Sanity check */
+ PJ_ASSERT_RETURN(splitcomb && port, PJ_EINVAL);
+
+ /* Make sure this is really a splitcomb port */
+ PJ_ASSERT_RETURN(sc->base.info.signature == SIGNATURE, PJ_EINVAL);
+
+ /* Check the channel number */
+ PJ_ASSERT_RETURN(ch_num < PJMEDIA_PIA_CCNT(&sc->base.info), PJ_EINVAL);
+
+ /* options is unused for now */
+ PJ_UNUSED_ARG(options);
+
+ sc->port_desc[ch_num].port = port;
+ sc->port_desc[ch_num].reversed = PJ_FALSE;
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Create reverse phase port for the specified channel.
+ */
+PJ_DEF(pj_status_t) pjmedia_splitcomb_create_rev_channel( pj_pool_t *pool,
+ pjmedia_port *splitcomb,
+ unsigned ch_num,
+ unsigned options,
+ pjmedia_port **p_chport)
+{
+ const pj_str_t name = pj_str("scomb-rev");
+ struct splitcomb *sc = (struct splitcomb*) splitcomb;
+ struct reverse_port *rport;
+ unsigned buf_cnt;
+ const pjmedia_audio_format_detail *sc_afd, *p_afd;
+ pjmedia_port *port;
+ pj_status_t status;
+
+ /* Sanity check */
+ PJ_ASSERT_RETURN(pool && splitcomb, PJ_EINVAL);
+
+ /* Make sure this is really a splitcomb port */
+ PJ_ASSERT_RETURN(sc->base.info.signature == SIGNATURE, PJ_EINVAL);
+
+ /* Check the channel number */
+ PJ_ASSERT_RETURN(ch_num < PJMEDIA_PIA_CCNT(&sc->base.info), PJ_EINVAL);
+
+ /* options is unused for now */
+ PJ_UNUSED_ARG(options);
+
+ sc_afd = pjmedia_format_get_audio_format_detail(&splitcomb->info.fmt, 1);
+
+ /* Create the port */
+ rport = PJ_POOL_ZALLOC_T(pool, struct reverse_port);
+ rport->parent = sc;
+ rport->ch_num = ch_num;
+
+ /* Initialize port info... */
+ port = &rport->base;
+ pjmedia_port_info_init(&port->info, &name, SIGNATURE_PORT,
+ sc_afd->clock_rate, 1,
+ sc_afd->bits_per_sample,
+ PJMEDIA_PIA_SPF(&splitcomb->info) /
+ sc_afd->channel_count);
+
+ p_afd = pjmedia_format_get_audio_format_detail(&port->info.fmt, 1);
+
+ /* ... and the callbacks */
+ port->put_frame = &rport_put_frame;
+ port->get_frame = &rport_get_frame;
+ port->on_destroy = &rport_on_destroy;
+
+ /* Buffer settings */
+ buf_cnt = options & 0xFF;
+ if (buf_cnt == 0)
+ buf_cnt = MAX_BUF_CNT;
+
+ rport->max_burst = MAX_BURST;
+ rport->max_null_frames = MAX_NULL_FRAMES;
+
+ /* Create downstream/put buffers */
+ status = pjmedia_delay_buf_create(pool, "scombdb-dn",
+ p_afd->clock_rate,
+ PJMEDIA_PIA_SPF(&port->info),
+ p_afd->channel_count,
+ buf_cnt * p_afd->frame_time_usec / 1000,
+ 0, &rport->buf[DIR_DOWNSTREAM].dbuf);
+ if (status != PJ_SUCCESS) {
+ return status;
+ }
+
+ /* Create upstream/get buffers */
+ status = pjmedia_delay_buf_create(pool, "scombdb-up",
+ p_afd->clock_rate,
+ PJMEDIA_PIA_SPF(&port->info),
+ p_afd->channel_count,
+ buf_cnt * p_afd->frame_time_usec / 1000,
+ 0, &rport->buf[DIR_UPSTREAM].dbuf);
+ if (status != PJ_SUCCESS) {
+ pjmedia_delay_buf_destroy(rport->buf[DIR_DOWNSTREAM].dbuf);
+ return status;
+ }
+
+ /* And temporary upstream/get buffer */
+ rport->tmp_up_buf = (pj_int16_t*)
+ pj_pool_alloc(pool,
+ PJMEDIA_PIA_AVG_FSZ(&port->info));
+
+ /* Save port in the splitcomb */
+ sc->port_desc[ch_num].port = &rport->base;
+ sc->port_desc[ch_num].reversed = PJ_TRUE;
+
+
+ /* Done */
+ *p_chport = port;
+ return status;
+}
+
+
+/*
+ * Extract one mono frame from a multichannel frame.
+ */
+static void extract_mono_frame( const pj_int16_t *in,
+ pj_int16_t *out,
+ unsigned ch,
+ unsigned ch_cnt,
+ unsigned samples_count)
+{
+ unsigned i;
+
+ in += ch;
+ for (i=0; i<samples_count; ++i) {
+ *out++ = *in;
+ in += ch_cnt;
+ }
+}
+
+
+/*
+ * Put one mono frame into a multichannel frame
+ */
+static void store_mono_frame( const pj_int16_t *in,
+ pj_int16_t *out,
+ unsigned ch,
+ unsigned ch_cnt,
+ unsigned samples_count)
+{
+ unsigned i;
+
+ out += ch;
+ for (i=0; i<samples_count; ++i) {
+ *out = *in++;
+ out += ch_cnt;
+ }
+}
+
+/* Update operation on the specified direction */
+static void op_update(struct reverse_port *rport, int dir, int op)
+{
+ char *dir_name[2] = {"downstream", "upstream"};
+
+ rport->buf[dir].level += op;
+
+ if (op == OP_PUT) {
+ rport->buf[dir].ts.u64 += PJMEDIA_PIA_SPF(&rport->base.info);
+ }
+
+ if (rport->buf[dir].paused) {
+ if (rport->buf[dir].level < -rport->max_burst) {
+ /* Prevent the level from overflowing and resets back to zero */
+ rport->buf[dir].level = -rport->max_burst;
+ } else if (rport->buf[dir].level > rport->max_burst) {
+ /* Prevent the level from overflowing and resets back to zero */
+ rport->buf[dir].level = rport->max_burst;
+ } else {
+ /* Level has fallen below max level, we can resume
+ * media flow.
+ */
+ PJ_LOG(5,(rport->base.info.name.ptr,
+ "Resuming media flow on %s direction (level=%d)",
+ dir_name[dir], rport->buf[dir].level));
+ rport->buf[dir].level = 0;
+ rport->buf[dir].paused = PJ_FALSE;
+
+ //This will cause disruption in audio, and it seems to be
+ //working fine without this anyway, so we disable it for now.
+ //pjmedia_delay_buf_learn(rport->buf[dir].dbuf);
+
+ }
+ } else {
+ if (rport->buf[dir].level >= rport->max_burst ||
+ rport->buf[dir].level <= -rport->max_burst)
+ {
+ /* Level has reached maximum level, the other side of
+ * rport is not sending/retrieving frames. Pause the
+ * rport on this direction.
+ */
+ PJ_LOG(5,(rport->base.info.name.ptr,
+ "Pausing media flow on %s direction (level=%d)",
+ dir_name[dir], rport->buf[dir].level));
+ rport->buf[dir].paused = PJ_TRUE;
+ }
+ }
+}
+
+
+/*
+ * "Write" a multichannel frame downstream. This would split
+ * the multichannel frame into individual mono channel, and write
+ * it to the appropriate port.
+ */
+static pj_status_t put_frame(pjmedia_port *this_port,
+ pjmedia_frame *frame)
+{
+ struct splitcomb *sc = (struct splitcomb*) this_port;
+ unsigned ch;
+
+ /* Handle null frame */
+ if (frame->type == PJMEDIA_FRAME_TYPE_NONE) {
+ for (ch=0; ch < PJMEDIA_PIA_CCNT(&this_port->info); ++ch) {
+ pjmedia_port *port = sc->port_desc[ch].port;
+
+ if (!port) continue;
+
+ if (!sc->port_desc[ch].reversed) {
+ pjmedia_port_put_frame(port, frame);
+ } else {
+ struct reverse_port *rport = (struct reverse_port*)port;
+
+ /* Update the number of NULL frames received. Once we have too
+ * many of this, we'll stop calling op_update() to let the
+ * media be suspended.
+ */
+
+ if (++rport->buf[DIR_DOWNSTREAM].null_cnt >
+ rport->max_null_frames)
+ {
+ /* Prevent the counter from overflowing and resetting
+ * back to zero
+ */
+ rport->buf[DIR_DOWNSTREAM].null_cnt =
+ rport->max_null_frames + 1;
+ continue;
+ }
+
+ /* Write zero port to delaybuf so that it doesn't underflow.
+ * If we don't do this, get_frame() on this direction will
+ * cause delaybuf to generate missing frame and the last
+ * frame transmitted to delaybuf will be replayed multiple
+ * times, which doesn't sound good.
+ */
+
+ /* Update rport state. */
+ op_update(rport, DIR_DOWNSTREAM, OP_PUT);
+
+ /* Discard frame if rport is paused on this direction */
+ if (rport->buf[DIR_DOWNSTREAM].paused)
+ continue;
+
+ /* Generate zero frame. */
+ pjmedia_zero_samples(sc->put_buf,
+ PJMEDIA_PIA_SPF(&this_port->info));
+
+ /* Put frame to delay buffer */
+ pjmedia_delay_buf_put(rport->buf[DIR_DOWNSTREAM].dbuf,
+ sc->put_buf);
+
+ }
+ }
+ return PJ_SUCCESS;
+ }
+
+ /* Not sure how we would handle partial frame, so better reject
+ * it for now.
+ */
+ PJ_ASSERT_RETURN(frame->size == PJMEDIA_PIA_AVG_FSZ(&this_port->info),
+ PJ_EINVAL);
+
+ /*
+ * Write mono frame into each channels
+ */
+ for (ch=0; ch < PJMEDIA_PIA_CCNT(&this_port->info); ++ch) {
+ pjmedia_port *port = sc->port_desc[ch].port;
+
+ if (!port)
+ continue;
+
+ /* Extract the mono frame to temporary buffer */
+ extract_mono_frame((const pj_int16_t*)frame->buf, sc->put_buf, ch,
+ PJMEDIA_PIA_CCNT(&this_port->info),
+ (unsigned)frame->size * 8 /
+ PJMEDIA_PIA_BITS(&this_port->info) /
+ PJMEDIA_PIA_CCNT(&this_port->info));
+
+ if (!sc->port_desc[ch].reversed) {
+ /* Write to normal port */
+ pjmedia_frame mono_frame;
+
+ mono_frame.buf = sc->put_buf;
+ mono_frame.size = frame->size / PJMEDIA_PIA_CCNT(&this_port->info);
+ mono_frame.type = frame->type;
+ mono_frame.timestamp.u64 = frame->timestamp.u64;
+
+ /* Write */
+ pjmedia_port_put_frame(port, &mono_frame);
+
+ } else {
+ /* Write to reversed phase port */
+ struct reverse_port *rport = (struct reverse_port*)port;
+
+ /* Reset NULL frame counter */
+ rport->buf[DIR_DOWNSTREAM].null_cnt = 0;
+
+ /* Update rport state. */
+ op_update(rport, DIR_DOWNSTREAM, OP_PUT);
+
+ if (!rport->buf[DIR_DOWNSTREAM].paused) {
+ pjmedia_delay_buf_put(rport->buf[DIR_DOWNSTREAM].dbuf,
+ sc->put_buf);
+ }
+ }
+ }
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Get a multichannel frame upstream.
+ * This will get mono channel frame from each port and put the
+ * mono frame into the multichannel frame.
+ */
+static pj_status_t get_frame(pjmedia_port *this_port,
+ pjmedia_frame *frame)
+{
+ struct splitcomb *sc = (struct splitcomb*) this_port;
+ unsigned ch;
+ pj_bool_t has_frame = PJ_FALSE;
+
+ /* Read frame from each port */
+ for (ch=0; ch < PJMEDIA_PIA_CCNT(&this_port->info); ++ch) {
+ pjmedia_port *port = sc->port_desc[ch].port;
+ pjmedia_frame mono_frame;
+ pj_status_t status;
+
+ if (!port) {
+ pjmedia_zero_samples(sc->get_buf,
+ PJMEDIA_PIA_SPF(&this_port->info) /
+ PJMEDIA_PIA_CCNT(&this_port->info));
+
+ } else if (sc->port_desc[ch].reversed == PJ_FALSE) {
+ /* Read from normal port */
+ mono_frame.buf = sc->get_buf;
+ mono_frame.size = PJMEDIA_PIA_AVG_FSZ(&port->info);
+ mono_frame.timestamp.u64 = frame->timestamp.u64;
+
+ status = pjmedia_port_get_frame(port, &mono_frame);
+ if (status != PJ_SUCCESS ||
+ mono_frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
+ {
+ pjmedia_zero_samples(sc->get_buf,
+ PJMEDIA_PIA_SPF(&port->info));
+ }
+
+ frame->timestamp.u64 = mono_frame.timestamp.u64;
+
+ } else {
+ /* Read from temporary buffer for reverse port */
+ struct reverse_port *rport = (struct reverse_port*)port;
+
+ /* Update rport state. */
+ op_update(rport, DIR_UPSTREAM, OP_GET);
+
+ if (!rport->buf[DIR_UPSTREAM].paused) {
+ pjmedia_delay_buf_get(rport->buf[DIR_UPSTREAM].dbuf,
+ sc->get_buf);
+
+ } else {
+ pjmedia_zero_samples(sc->get_buf,
+ PJMEDIA_PIA_SPF(&port->info));
+ }
+
+ frame->timestamp.u64 = rport->buf[DIR_UPSTREAM].ts.u64;
+ }
+
+ /* Combine the mono frame into multichannel frame */
+ store_mono_frame(sc->get_buf,
+ (pj_int16_t*)frame->buf, ch,
+ PJMEDIA_PIA_CCNT(&this_port->info),
+ PJMEDIA_PIA_SPF(&this_port->info) /
+ PJMEDIA_PIA_CCNT(&this_port->info));
+
+ has_frame = PJ_TRUE;
+ }
+
+ /* Return NO_FRAME is we don't get any frames from downstream ports */
+ if (has_frame) {
+ frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
+ frame->size = PJMEDIA_PIA_AVG_FSZ(&this_port->info);
+ } else
+ frame->type = PJMEDIA_FRAME_TYPE_NONE;
+
+ return PJ_SUCCESS;
+}
+
+
+static pj_status_t on_destroy(pjmedia_port *this_port)
+{
+ /* Nothing to do for the splitcomb
+ * Reverse ports must be destroyed separately.
+ */
+ PJ_UNUSED_ARG(this_port);
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Put a frame in the reverse port (upstream direction). This frame
+ * will be picked up by get_frame() above.
+ */
+static pj_status_t rport_put_frame(pjmedia_port *this_port,
+ pjmedia_frame *frame)
+{
+ struct reverse_port *rport = (struct reverse_port*) this_port;
+
+ pj_assert(frame->size <= PJMEDIA_PIA_AVG_FSZ(&rport->base.info));
+
+ /* Handle NULL frame */
+ if (frame->type != PJMEDIA_FRAME_TYPE_AUDIO) {
+ /* Update the number of NULL frames received. Once we have too
+ * many of this, we'll stop calling op_update() to let the
+ * media be suspended.
+ */
+ if (++rport->buf[DIR_UPSTREAM].null_cnt > rport->max_null_frames) {
+ /* Prevent the counter from overflowing and resetting back
+ * to zero
+ */
+ rport->buf[DIR_UPSTREAM].null_cnt = rport->max_null_frames + 1;
+ return PJ_SUCCESS;
+ }
+
+ /* Write zero port to delaybuf so that it doesn't underflow.
+ * If we don't do this, get_frame() on this direction will
+ * cause delaybuf to generate missing frame and the last
+ * frame transmitted to delaybuf will be replayed multiple
+ * times, which doesn't sound good.
+ */
+
+ /* Update rport state. */
+ op_update(rport, DIR_UPSTREAM, OP_PUT);
+
+ /* Discard frame if rport is paused on this direction */
+ if (rport->buf[DIR_UPSTREAM].paused)
+ return PJ_SUCCESS;
+
+ /* Generate zero frame. */
+ pjmedia_zero_samples(rport->tmp_up_buf,
+ PJMEDIA_PIA_SPF(&this_port->info));
+
+ /* Put frame to delay buffer */
+ return pjmedia_delay_buf_put(rport->buf[DIR_UPSTREAM].dbuf,
+ rport->tmp_up_buf);
+ }
+
+ /* Not sure how to handle partial frame, so better reject for now */
+ PJ_ASSERT_RETURN(frame->size == PJMEDIA_PIA_AVG_FSZ(&this_port->info),
+ PJ_EINVAL);
+
+ /* Reset NULL frame counter */
+ rport->buf[DIR_UPSTREAM].null_cnt = 0;
+
+ /* Update rport state. */
+ op_update(rport, DIR_UPSTREAM, OP_PUT);
+
+ /* Discard frame if rport is paused on this direction */
+ if (rport->buf[DIR_UPSTREAM].paused)
+ return PJ_SUCCESS;
+
+ /* Unfortunately must copy to temporary buffer since delay buf
+ * modifies the frame content.
+ */
+ pjmedia_copy_samples(rport->tmp_up_buf, (const pj_int16_t*)frame->buf,
+ PJMEDIA_PIA_SPF(&this_port->info));
+
+ /* Put frame to delay buffer */
+ return pjmedia_delay_buf_put(rport->buf[DIR_UPSTREAM].dbuf,
+ rport->tmp_up_buf);
+}
+
+
+/* Get a mono frame from a reversed phase channel (downstream direction).
+ * The frame is put by put_frame() call to the splitcomb.
+ */
+static pj_status_t rport_get_frame(pjmedia_port *this_port,
+ pjmedia_frame *frame)
+{
+ struct reverse_port *rport = (struct reverse_port*) this_port;
+
+ /* Update state */
+ op_update(rport, DIR_DOWNSTREAM, OP_GET);
+
+ /* Return no frame if media flow on this direction is being
+ * paused.
+ */
+ if (rport->buf[DIR_DOWNSTREAM].paused) {
+ frame->type = PJMEDIA_FRAME_TYPE_NONE;
+ return PJ_SUCCESS;
+ }
+
+ /* Get frame from delay buffer */
+ frame->size = PJMEDIA_PIA_AVG_FSZ(&this_port->info);
+ frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
+ frame->timestamp.u64 = rport->buf[DIR_DOWNSTREAM].ts.u64;
+
+ return pjmedia_delay_buf_get(rport->buf[DIR_DOWNSTREAM].dbuf,
+ (short*)frame->buf);
+}
+
+
+static pj_status_t rport_on_destroy(pjmedia_port *this_port)
+{
+ struct reverse_port *rport = (struct reverse_port*) this_port;
+
+ pjmedia_delay_buf_destroy(rport->buf[DIR_DOWNSTREAM].dbuf);
+ pjmedia_delay_buf_destroy(rport->buf[DIR_UPSTREAM].dbuf);
+
+ return PJ_SUCCESS;
+}
+
diff --git a/jni/pjproject-android/.svn/pristine/c6/c68e951e121fbd3df5d00f3a607de42a5903531a.svn-base b/jni/pjproject-android/.svn/pristine/c6/c68e951e121fbd3df5d00f3a607de42a5903531a.svn-base
new file mode 100644
index 0000000..a8dd2f3
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c6/c68e951e121fbd3df5d00f3a607de42a5903531a.svn-base
@@ -0,0 +1,2 @@
+EXPORTS
+ initpy_pjsua
diff --git a/jni/pjproject-android/.svn/pristine/c6/c694303933d89e342b17f68b7944e7b73e24838a.svn-base b/jni/pjproject-android/.svn/pristine/c6/c694303933d89e342b17f68b7944e7b73e24838a.svn-base
new file mode 100644
index 0000000..571b807
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c6/c694303933d89e342b17f68b7944e7b73e24838a.svn-base
@@ -0,0 +1,630 @@
+/* $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 <pjsip-ua/sip_xfer.h>
+#include <pjsip-simple/evsub_msg.h>
+#include <pjsip/sip_dialog.h>
+#include <pjsip/sip_errno.h>
+#include <pjsip/sip_endpoint.h>
+#include <pjsip/sip_module.h>
+#include <pjsip/sip_transport.h>
+#include <pj/assert.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+
+/* Subscription expiration */
+#ifndef PJSIP_XFER_EXPIRES
+# define PJSIP_XFER_EXPIRES 600
+#endif
+
+
+/*
+ * Refer module (mod-refer)
+ */
+static struct pjsip_module mod_xfer =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-refer", 9 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_DIALOG_USAGE, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ NULL, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+};
+
+
+/* Declare PJSIP_REFER_METHOD, so that if somebody declares this in
+ * sip_msg.h we can catch the error here.
+ */
+enum
+{
+ PJSIP_REFER_METHOD = PJSIP_OTHER_METHOD
+};
+
+PJ_DEF_DATA(const pjsip_method) pjsip_refer_method = {
+ (pjsip_method_e) PJSIP_REFER_METHOD,
+ { "REFER", 5}
+};
+
+PJ_DEF(const pjsip_method*) pjsip_get_refer_method()
+{
+ return &pjsip_refer_method;
+}
+
+/*
+ * String constants
+ */
+const pj_str_t STR_REFER = { "refer", 5 };
+const pj_str_t STR_MESSAGE = { "message", 7 };
+const pj_str_t STR_SIPFRAG = { "sipfrag", 7 };
+const pj_str_t STR_SIPFRAG_VERSION = {";version=2.0", 12 };
+
+
+/*
+ * Transfer struct.
+ */
+struct pjsip_xfer
+{
+ pjsip_evsub *sub; /**< Event subscribtion record. */
+ pjsip_dialog *dlg; /**< The dialog. */
+ pjsip_evsub_user user_cb; /**< The user callback. */
+ pj_str_t refer_to_uri; /**< The full Refer-To URI. */
+ int last_st_code; /**< st_code sent in last NOTIFY */
+ pj_str_t last_st_text; /**< st_text sent in last NOTIFY */
+};
+
+
+typedef struct pjsip_xfer pjsip_xfer;
+
+
+
+/*
+ * Forward decl for evsub callback.
+ */
+static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);
+static void xfer_on_evsub_tsx_state( pjsip_evsub *sub, pjsip_transaction *tsx,
+ pjsip_event *event);
+static void xfer_on_evsub_rx_refresh( pjsip_evsub *sub,
+ pjsip_rx_data *rdata,
+ int *p_st_code,
+ pj_str_t **p_st_text,
+ pjsip_hdr *res_hdr,
+ pjsip_msg_body **p_body);
+static void xfer_on_evsub_rx_notify( pjsip_evsub *sub,
+ pjsip_rx_data *rdata,
+ int *p_st_code,
+ pj_str_t **p_st_text,
+ pjsip_hdr *res_hdr,
+ pjsip_msg_body **p_body);
+static void xfer_on_evsub_client_refresh(pjsip_evsub *sub);
+static void xfer_on_evsub_server_timeout(pjsip_evsub *sub);
+
+
+/*
+ * Event subscription callback for xference.
+ */
+static pjsip_evsub_user xfer_user =
+{
+ &xfer_on_evsub_state,
+ &xfer_on_evsub_tsx_state,
+ &xfer_on_evsub_rx_refresh,
+ &xfer_on_evsub_rx_notify,
+ &xfer_on_evsub_client_refresh,
+ &xfer_on_evsub_server_timeout,
+};
+
+
+
+
+/*
+ * Initialize the REFER subsystem.
+ */
+PJ_DEF(pj_status_t) pjsip_xfer_init_module(pjsip_endpoint *endpt)
+{
+ const pj_str_t accept = { "message/sipfrag;version=2.0", 27 };
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(endpt != NULL, PJ_EINVAL);
+ PJ_ASSERT_RETURN(mod_xfer.id == -1, PJ_EINVALIDOP);
+
+ status = pjsip_endpt_register_module(endpt, &mod_xfer);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ status = pjsip_endpt_add_capability( endpt, &mod_xfer, PJSIP_H_ALLOW,
+ NULL, 1,
+ &pjsip_get_refer_method()->name);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ status = pjsip_evsub_register_pkg(&mod_xfer, &STR_REFER,
+ PJSIP_XFER_EXPIRES, 1, &accept);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Create transferer (sender of REFER request).
+ *
+ */
+PJ_DEF(pj_status_t) pjsip_xfer_create_uac( pjsip_dialog *dlg,
+ const pjsip_evsub_user *user_cb,
+ pjsip_evsub **p_evsub )
+{
+ pj_status_t status;
+ pjsip_xfer *xfer;
+ pjsip_evsub *sub;
+
+ PJ_ASSERT_RETURN(dlg && p_evsub, PJ_EINVAL);
+
+ pjsip_dlg_inc_lock(dlg);
+
+ /* Create event subscription */
+ status = pjsip_evsub_create_uac( dlg, &xfer_user, &STR_REFER,
+ PJSIP_EVSUB_NO_EVENT_ID, &sub);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ /* Create xfer session */
+ xfer = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_xfer);
+ xfer->dlg = dlg;
+ xfer->sub = sub;
+ if (user_cb)
+ pj_memcpy(&xfer->user_cb, user_cb, sizeof(pjsip_evsub_user));
+
+ /* Attach to evsub */
+ pjsip_evsub_set_mod_data(sub, mod_xfer.id, xfer);
+
+ *p_evsub = sub;
+
+on_return:
+ pjsip_dlg_dec_lock(dlg);
+ return status;
+
+}
+
+
+
+
+/*
+ * Create transferee (receiver of REFER request).
+ *
+ */
+PJ_DEF(pj_status_t) pjsip_xfer_create_uas( pjsip_dialog *dlg,
+ const pjsip_evsub_user *user_cb,
+ pjsip_rx_data *rdata,
+ pjsip_evsub **p_evsub )
+{
+ pjsip_evsub *sub;
+ pjsip_xfer *xfer;
+ const pj_str_t STR_EVENT = {"Event", 5 };
+ pjsip_event_hdr *event_hdr;
+ pj_status_t status;
+
+ /* Check arguments */
+ PJ_ASSERT_RETURN(dlg && rdata && p_evsub, PJ_EINVAL);
+
+ /* Must be request message */
+ PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,
+ PJSIP_ENOTREQUESTMSG);
+
+ /* Check that request is REFER */
+ PJ_ASSERT_RETURN(pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
+ pjsip_get_refer_method())==0,
+ PJSIP_ENOTREFER);
+
+ /* Lock dialog */
+ pjsip_dlg_inc_lock(dlg);
+
+ /* The evsub framework expects an Event header in the request,
+ * while a REFER request conveniently doesn't have one (pun intended!).
+ * So create a dummy Event header.
+ */
+ if (pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,
+ &STR_EVENT, NULL)==NULL)
+ {
+ event_hdr = pjsip_event_hdr_create(rdata->tp_info.pool);
+ event_hdr->event_type = STR_REFER;
+ pjsip_msg_add_hdr(rdata->msg_info.msg, (pjsip_hdr*)event_hdr);
+ }
+
+ /* Create server subscription */
+ status = pjsip_evsub_create_uas( dlg, &xfer_user, rdata,
+ PJSIP_EVSUB_NO_EVENT_ID, &sub);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ /* Create server xfer subscription */
+ xfer = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_xfer);
+ xfer->dlg = dlg;
+ xfer->sub = sub;
+ if (user_cb)
+ pj_memcpy(&xfer->user_cb, user_cb, sizeof(pjsip_evsub_user));
+
+ /* Attach to evsub */
+ pjsip_evsub_set_mod_data(sub, mod_xfer.id, xfer);
+
+ /* Done: */
+ *p_evsub = sub;
+
+on_return:
+ pjsip_dlg_dec_lock(dlg);
+ return status;
+}
+
+
+
+/*
+ * Call this function to create request to initiate REFER subscription.
+ *
+ */
+PJ_DEF(pj_status_t) pjsip_xfer_initiate( pjsip_evsub *sub,
+ const pj_str_t *refer_to_uri,
+ pjsip_tx_data **p_tdata)
+{
+ pjsip_xfer *xfer;
+ const pj_str_t refer_to = { "Refer-To", 8};
+ pjsip_tx_data *tdata;
+ pjsip_generic_string_hdr *hdr;
+ pj_status_t status;
+
+ /* sub and p_tdata argument must be valid. */
+ PJ_ASSERT_RETURN(sub && p_tdata, PJ_EINVAL);
+
+
+ /* Get the xfer object. */
+ xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
+ PJ_ASSERT_RETURN(xfer != NULL, PJSIP_ENOREFERSESSION);
+
+ /* refer_to_uri argument MAY be NULL for subsequent REFER requests,
+ * but it MUST be specified in the first REFER.
+ */
+ PJ_ASSERT_RETURN((refer_to_uri || xfer->refer_to_uri.slen), PJ_EINVAL);
+
+ /* Lock dialog. */
+ pjsip_dlg_inc_lock(xfer->dlg);
+
+ /* Create basic REFER request */
+ status = pjsip_evsub_initiate(sub, pjsip_get_refer_method(), -1,
+ &tdata);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+ /* Save Refer-To URI. */
+ if (refer_to_uri == NULL) {
+ refer_to_uri = &xfer->refer_to_uri;
+ } else {
+ pj_strdup(xfer->dlg->pool, &xfer->refer_to_uri, refer_to_uri);
+ }
+
+ /* Create and add Refer-To header. */
+ hdr = pjsip_generic_string_hdr_create(tdata->pool, &refer_to,
+ refer_to_uri);
+ if (!hdr) {
+ pjsip_tx_data_dec_ref(tdata);
+ status = PJ_ENOMEM;
+ goto on_return;
+ }
+
+ pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hdr);
+
+
+ /* Done. */
+ *p_tdata = tdata;
+
+ status = PJ_SUCCESS;
+
+on_return:
+ pjsip_dlg_dec_lock(xfer->dlg);
+ return status;
+}
+
+
+/*
+ * Accept the incoming REFER request by sending 2xx response.
+ *
+ */
+PJ_DEF(pj_status_t) pjsip_xfer_accept( pjsip_evsub *sub,
+ pjsip_rx_data *rdata,
+ int st_code,
+ const pjsip_hdr *hdr_list )
+{
+ /*
+ * Don't need to add custom headers, so just call basic
+ * evsub response.
+ */
+ return pjsip_evsub_accept( sub, rdata, st_code, hdr_list );
+}
+
+
+/*
+ * For notifier, create NOTIFY request to subscriber, and set the state
+ * of the subscription.
+ */
+PJ_DEF(pj_status_t) pjsip_xfer_notify( pjsip_evsub *sub,
+ pjsip_evsub_state state,
+ int xfer_st_code,
+ const pj_str_t *xfer_st_text,
+ pjsip_tx_data **p_tdata)
+{
+ pjsip_tx_data *tdata;
+ pjsip_xfer *xfer;
+ pjsip_param *param;
+ const pj_str_t reason = { "noresource", 10 };
+ char *body;
+ int bodylen;
+ pjsip_msg_body *msg_body;
+ pj_status_t status;
+
+
+ /* Check arguments. */
+ PJ_ASSERT_RETURN(sub, PJ_EINVAL);
+
+ /* Get the xfer object. */
+ xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
+ PJ_ASSERT_RETURN(xfer != NULL, PJSIP_ENOREFERSESSION);
+
+
+ /* Lock object. */
+ pjsip_dlg_inc_lock(xfer->dlg);
+
+ /* Create the NOTIFY request.
+ * Note that reason is only used when state is TERMINATED, and
+ * the defined termination reason for REFER is "noresource".
+ */
+ status = pjsip_evsub_notify( sub, state, NULL, &reason, &tdata);
+ if (status != PJ_SUCCESS)
+ goto on_return;
+
+
+ /* Check status text */
+ if (xfer_st_text==NULL || xfer_st_text->slen==0)
+ xfer_st_text = pjsip_get_status_text(xfer_st_code);
+
+ /* Save st_code and st_text, for current_notify() */
+ xfer->last_st_code = xfer_st_code;
+ pj_strdup(xfer->dlg->pool, &xfer->last_st_text, xfer_st_text);
+
+ /* Create sipfrag content. */
+ body = (char*) pj_pool_alloc(tdata->pool, 128);
+ bodylen = pj_ansi_snprintf(body, 128, "SIP/2.0 %u %.*s\r\n",
+ xfer_st_code,
+ (int)xfer_st_text->slen,
+ xfer_st_text->ptr);
+ PJ_ASSERT_ON_FAIL(bodylen > 0 && bodylen < 128,
+ {status=PJ_EBUG; pjsip_tx_data_dec_ref(tdata);
+ goto on_return; });
+
+
+ /* Create SIP message body. */
+ msg_body = PJ_POOL_ZALLOC_T(tdata->pool, pjsip_msg_body);
+ pjsip_media_type_init(&msg_body->content_type, (pj_str_t*)&STR_MESSAGE,
+ (pj_str_t*)&STR_SIPFRAG);
+ msg_body->data = body;
+ msg_body->len = bodylen;
+ msg_body->print_body = &pjsip_print_text_body;
+ msg_body->clone_data = &pjsip_clone_text_data;
+
+ param = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
+ param->name = pj_str("version");
+ param->value = pj_str("2.0");
+ pj_list_push_back(&msg_body->content_type.param, param);
+
+ /* Attach sipfrag body. */
+ tdata->msg->body = msg_body;
+
+
+ /* Done. */
+ *p_tdata = tdata;
+
+
+on_return:
+ pjsip_dlg_dec_lock(xfer->dlg);
+ return status;
+
+}
+
+
+/*
+ * Send current state and the last sipfrag body.
+ */
+PJ_DEF(pj_status_t) pjsip_xfer_current_notify( pjsip_evsub *sub,
+ pjsip_tx_data **p_tdata )
+{
+ pjsip_xfer *xfer;
+ pj_status_t status;
+
+
+ /* Check arguments. */
+ PJ_ASSERT_RETURN(sub, PJ_EINVAL);
+
+ /* Get the xfer object. */
+ xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
+ PJ_ASSERT_RETURN(xfer != NULL, PJSIP_ENOREFERSESSION);
+
+ pjsip_dlg_inc_lock(xfer->dlg);
+
+ status = pjsip_xfer_notify(sub, pjsip_evsub_get_state(sub),
+ xfer->last_st_code, &xfer->last_st_text,
+ p_tdata);
+
+ pjsip_dlg_dec_lock(xfer->dlg);
+
+ return status;
+}
+
+
+/*
+ * Send request message.
+ */
+PJ_DEF(pj_status_t) pjsip_xfer_send_request( pjsip_evsub *sub,
+ pjsip_tx_data *tdata)
+{
+ return pjsip_evsub_send_request(sub, tdata);
+}
+
+
+/*
+ * This callback is called by event subscription when subscription
+ * state has changed.
+ */
+static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
+{
+ pjsip_xfer *xfer;
+
+ xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
+ PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
+
+ if (xfer->user_cb.on_evsub_state)
+ (*xfer->user_cb.on_evsub_state)(sub, event);
+
+}
+
+/*
+ * Called when transaction state has changed.
+ */
+static void xfer_on_evsub_tsx_state( pjsip_evsub *sub, pjsip_transaction *tsx,
+ pjsip_event *event)
+{
+ pjsip_xfer *xfer;
+
+ xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
+ PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
+
+ if (xfer->user_cb.on_tsx_state)
+ (*xfer->user_cb.on_tsx_state)(sub, tsx, event);
+}
+
+/*
+ * Called when REFER is received to refresh subscription.
+ */
+static void xfer_on_evsub_rx_refresh( pjsip_evsub *sub,
+ pjsip_rx_data *rdata,
+ int *p_st_code,
+ pj_str_t **p_st_text,
+ pjsip_hdr *res_hdr,
+ pjsip_msg_body **p_body)
+{
+ pjsip_xfer *xfer;
+
+ xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
+ PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
+
+ if (xfer->user_cb.on_rx_refresh) {
+ (*xfer->user_cb.on_rx_refresh)(sub, rdata, p_st_code, p_st_text,
+ res_hdr, p_body);
+
+ } else {
+ /* Implementors MUST send NOTIFY if it implements on_rx_refresh
+ * (implementor == "us" from evsub point of view.
+ */
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ if (pjsip_evsub_get_state(sub)==PJSIP_EVSUB_STATE_TERMINATED) {
+ status = pjsip_xfer_notify( sub, PJSIP_EVSUB_STATE_TERMINATED,
+ xfer->last_st_code,
+ &xfer->last_st_text,
+ &tdata);
+ } else {
+ status = pjsip_xfer_current_notify(sub, &tdata);
+ }
+
+ if (status == PJ_SUCCESS)
+ pjsip_xfer_send_request(sub, tdata);
+ }
+}
+
+
+/*
+ * Called when NOTIFY is received.
+ */
+static void xfer_on_evsub_rx_notify( pjsip_evsub *sub,
+ pjsip_rx_data *rdata,
+ int *p_st_code,
+ pj_str_t **p_st_text,
+ pjsip_hdr *res_hdr,
+ pjsip_msg_body **p_body)
+{
+ pjsip_xfer *xfer;
+
+ xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
+ PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
+
+ if (xfer->user_cb.on_rx_notify)
+ (*xfer->user_cb.on_rx_notify)(sub, rdata, p_st_code, p_st_text,
+ res_hdr, p_body);
+}
+
+/*
+ * Called when it's time to send SUBSCRIBE.
+ */
+static void xfer_on_evsub_client_refresh(pjsip_evsub *sub)
+{
+ pjsip_xfer *xfer;
+
+ xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
+ PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
+
+ if (xfer->user_cb.on_client_refresh) {
+ (*xfer->user_cb.on_client_refresh)(sub);
+ } else {
+ pj_status_t status;
+ pjsip_tx_data *tdata;
+
+ status = pjsip_evsub_initiate(sub, NULL, PJSIP_XFER_EXPIRES, &tdata);
+ if (status == PJ_SUCCESS)
+ pjsip_xfer_send_request(sub, tdata);
+ }
+}
+
+
+/*
+ * Called when no refresh is received after the interval.
+ */
+static void xfer_on_evsub_server_timeout(pjsip_evsub *sub)
+{
+ pjsip_xfer *xfer;
+
+ xfer = (pjsip_xfer*) pjsip_evsub_get_mod_data(sub, mod_xfer.id);
+ PJ_ASSERT_ON_FAIL(xfer!=NULL, {return;});
+
+ if (xfer->user_cb.on_server_timeout) {
+ (*xfer->user_cb.on_server_timeout)(sub);
+ } else {
+ pj_status_t status;
+ pjsip_tx_data *tdata;
+
+ status = pjsip_xfer_notify(sub, PJSIP_EVSUB_STATE_TERMINATED,
+ xfer->last_st_code,
+ &xfer->last_st_text, &tdata);
+ if (status == PJ_SUCCESS)
+ pjsip_xfer_send_request(sub, tdata);
+ }
+}
+
diff --git a/jni/pjproject-android/.svn/pristine/c6/c6a03e7b682ccfe6359ffbf7f3d5d3b3ccfae32d.svn-base b/jni/pjproject-android/.svn/pristine/c6/c6a03e7b682ccfe6359ffbf7f3d5d3b3ccfae32d.svn-base
new file mode 100644
index 0000000..6ca5eab
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c6/c6a03e7b682ccfe6359ffbf7f3d5d3b3ccfae32d.svn-base
@@ -0,0 +1,41 @@
+TARGET pjstun_client.exe
+TARGETTYPE exe
+UID 0x0 0xA000000A
+
+OPTION ARMCC --gnu
+
+SOURCEPATH ..\pjnath\src\pjstun-client
+
+MACRO PJ_M_I386=1
+MACRO PJ_SYMBIAN=1
+
+// PJSTUN-CLIENT files
+
+SOURCE client_main.c
+
+//SOURCE main_symbian.cpp
+
+
+SYSTEMINCLUDE ..\pjlib\include
+SYSTEMINCLUDE ..\pjlib-util\include
+SYSTEMINCLUDE ..\pjnath\include
+
+SYSTEMINCLUDE \epoc32\include
+SYSTEMINCLUDE \epoc32\include\libc
+
+#if defined(PJ_BUILD_DLL)
+MACRO PJ_DLL
+LIBRARY pjnath.lib pjlib_util.lib pjlib.lib
+#else
+STATICLIBRARY pjnath.lib pjlib_util.lib pjlib.lib
+#endif
+
+LIBRARY esock.lib insock.lib charconv.lib euser.lib estlib.lib
+
+#ifdef WINSCW
+STATICLIBRARY eexe.lib ecrt0.lib
+#endif
+
+
+CAPABILITY None
+
diff --git a/jni/pjproject-android/.svn/pristine/c6/c6a16c32f19599cd74378f514ace8b32739fdc18.svn-base b/jni/pjproject-android/.svn/pristine/c6/c6a16c32f19599cd74378f514ace8b32739fdc18.svn-base
new file mode 100644
index 0000000..ac0ee83
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c6/c6a16c32f19599cd74378f514ace8b32739fdc18.svn-base
@@ -0,0 +1,235 @@
+/* $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 "test.h"
+#include <pj/os.h>
+#include <pj/log.h>
+#include <pj/rand.h>
+
+
+/**
+ * \page page_pjlib_timestamp_test Test: Timestamp
+ *
+ * This file provides implementation of timestamp_test()
+ *
+ * \section timestamp_test_sec Scope of the Test
+ *
+ * This tests whether timestamp API works.
+ *
+ * API tested:
+ * - pj_get_timestamp_freq()
+ * - pj_get_timestamp()
+ * - pj_elapsed_usec()
+ * - PJ_LOG()
+ *
+ *
+ * This file is <b>pjlib-test/timestamp.c</b>
+ *
+ * \include pjlib-test/timestamp.c
+ */
+
+#if INCLUDE_TIMESTAMP_TEST
+
+#define THIS_FILE "timestamp"
+
+static int timestamp_accuracy()
+{
+ pj_timestamp freq, t1, t2;
+ pj_time_val tv1, tv2, tvtmp;
+ pj_int64_t msec, tics;
+ pj_int64_t diff;
+
+ PJ_LOG(3,(THIS_FILE, "...testing frequency accuracy (pls wait)"));
+
+ pj_get_timestamp_freq(&freq);
+
+ /* Get the start time */
+ pj_gettimeofday(&tvtmp);
+ do {
+ pj_gettimeofday(&tv1);
+ } while (PJ_TIME_VAL_EQ(tvtmp, tv1));
+ pj_get_timestamp(&t1);
+
+ /* Sleep for 10 seconds */
+ pj_thread_sleep(10000);
+
+ /* Get end time */
+ pj_gettimeofday(&tvtmp);
+ do {
+ pj_gettimeofday(&tv2);
+ } while (PJ_TIME_VAL_EQ(tvtmp, tv2));
+ pj_get_timestamp(&t2);
+
+ /* Get the elapsed time */
+ PJ_TIME_VAL_SUB(tv2, tv1);
+ msec = PJ_TIME_VAL_MSEC(tv2);
+
+ /* Check that the frequency match the elapsed time */
+ tics = t2.u64 - t1.u64;
+ diff = tics - (msec * freq.u64 / 1000);
+ if (diff < 0)
+ diff = -diff;
+
+ /* Only allow 1 msec mismatch */
+ if (diff > (pj_int64_t)(freq.u64 / 1000)) {
+ PJ_LOG(3,(THIS_FILE, "....error: timestamp drifted by %d usec after "
+ "%d msec",
+ (pj_uint32_t)(diff * 1000000 / freq.u64),
+ msec));
+ return -2000;
+
+ /* Otherwise just print warning if timestamp drifted by >1 usec */
+ } else if (diff > (pj_int64_t)(freq.u64 / 1000000)) {
+ PJ_LOG(3,(THIS_FILE, "....warning: timestamp drifted by %d usec after "
+ "%d msec",
+ (pj_uint32_t)(diff * 1000000 / freq.u64),
+ msec));
+ } else {
+ PJ_LOG(3,(THIS_FILE, "....good. Timestamp is accurate down to"
+ " nearest usec."));
+ }
+
+ return 0;
+}
+
+
+int timestamp_test(void)
+{
+ enum { CONSECUTIVE_LOOP = 100 };
+ volatile unsigned i;
+ pj_timestamp freq, t1, t2;
+ pj_time_val tv1, tv2;
+ unsigned elapsed;
+ pj_status_t rc;
+
+ PJ_LOG(3,(THIS_FILE, "...Testing timestamp (high res time)"));
+
+ /* Get and display timestamp frequency. */
+ if ((rc=pj_get_timestamp_freq(&freq)) != PJ_SUCCESS) {
+ app_perror("...ERROR: get timestamp freq", rc);
+ return -1000;
+ }
+
+ PJ_LOG(3,(THIS_FILE, "....frequency: hiword=%lu loword=%lu",
+ freq.u32.hi, freq.u32.lo));
+
+ PJ_LOG(3,(THIS_FILE, "...checking if time can run backwards (pls wait).."));
+
+ /*
+ * Check if consecutive readings should yield timestamp value
+ * that is bigger than previous value.
+ * First we get the first timestamp.
+ */
+ rc = pj_get_timestamp(&t1);
+ if (rc != PJ_SUCCESS) {
+ app_perror("...ERROR: pj_get_timestamp", rc);
+ return -1001;
+ }
+ rc = pj_gettimeofday(&tv1);
+ if (rc != PJ_SUCCESS) {
+ app_perror("...ERROR: pj_gettimeofday", rc);
+ return -1002;
+ }
+ for (i=0; i<CONSECUTIVE_LOOP; ++i) {
+
+ pj_thread_sleep(pj_rand() % 100);
+
+ rc = pj_get_timestamp(&t2);
+ if (rc != PJ_SUCCESS) {
+ app_perror("...ERROR: pj_get_timestamp", rc);
+ return -1003;
+ }
+ rc = pj_gettimeofday(&tv2);
+ if (rc != PJ_SUCCESS) {
+ app_perror("...ERROR: pj_gettimeofday", rc);
+ return -1004;
+ }
+
+ /* compare t2 with t1, expecting t2 >= t1. */
+ if (t2.u32.hi < t1.u32.hi ||
+ (t2.u32.hi == t1.u32.hi && t2.u32.lo < t1.u32.lo))
+ {
+ PJ_LOG(3,(THIS_FILE, "...ERROR: timestamp run backwards!"));
+ return -1005;
+ }
+
+ /* compare tv2 with tv1, expecting tv2 >= tv1. */
+ if (PJ_TIME_VAL_LT(tv2, tv1)) {
+ PJ_LOG(3,(THIS_FILE, "...ERROR: time run backwards!"));
+ return -1006;
+ }
+ }
+
+ /*
+ * Simple test to time some loop.
+ */
+ PJ_LOG(3,(THIS_FILE, "....testing simple 1000000 loop"));
+
+
+ /* Mark start time. */
+ if ((rc=pj_get_timestamp(&t1)) != PJ_SUCCESS) {
+ app_perror("....error: cat't get timestamp", rc);
+ return -1010;
+ }
+
+ /* Loop.. */
+ for (i=0; i<1000000; ++i) {
+ /* Try to do something so that smart compilers wont
+ * remove this silly loop.
+ */
+ null_func();
+ }
+
+ pj_thread_sleep(0);
+
+ /* Mark end time. */
+ pj_get_timestamp(&t2);
+
+ /* Get elapsed time in usec. */
+ elapsed = pj_elapsed_usec(&t1, &t2);
+ PJ_LOG(3,(THIS_FILE, "....elapsed: %u usec", (unsigned)elapsed));
+
+ /* See if elapsed time is "reasonable".
+ * This should be good even on 50Mhz embedded powerpc.
+ */
+ if (elapsed < 1 || elapsed > 1000000) {
+ PJ_LOG(3,(THIS_FILE, "....error: elapsed time outside window (%u, "
+ "t1.u32.hi=%u, t1.u32.lo=%u, "
+ "t2.u32.hi=%u, t2.u32.lo=%u)",
+ elapsed,
+ t1.u32.hi, t1.u32.lo, t2.u32.hi, t2.u32.lo));
+ return -1030;
+ }
+
+ /* Testing time/timestamp accuracy */
+ rc = timestamp_accuracy();
+ if (rc != 0)
+ return rc;
+
+ return 0;
+}
+
+
+#else
+/* To prevent warning about "translation unit is empty"
+ * when this test is disabled.
+ */
+int dummy_timestamp_test;
+#endif /* INCLUDE_TIMESTAMP_TEST */
+
diff --git a/jni/pjproject-android/.svn/pristine/c6/c6f38162fdff84973cf33852435ab7e25ac358d6.svn-base b/jni/pjproject-android/.svn/pristine/c6/c6f38162fdff84973cf33852435ab7e25ac358d6.svn-base
new file mode 100644
index 0000000..c78f48d
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/c6/c6f38162fdff84973cf33852435ab7e25ac358d6.svn-base
@@ -0,0 +1 @@
+#include "../../../portaudio/src/common/pa_stream.h"