* #36737: switch back to svn repo, remove assert in sip_transaction.c
diff --git a/jni/pjproject-android/.svn/pristine/36/360a9c86449a830b43cdb26bd62659073f971e98.svn-base b/jni/pjproject-android/.svn/pristine/36/360a9c86449a830b43cdb26bd62659073f971e98.svn-base
new file mode 100644
index 0000000..9d2fa65
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/36/360a9c86449a830b43cdb26bd62659073f971e98.svn-base
@@ -0,0 +1,367 @@
+/* $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"
+
+#if INCLUDE_CONCUR_TEST
+
+#define THIS_FILE	"concur_test.c"
+
+/****************************************************************************/
+#define WORKER_THREAD_CNT	4
+#define SERVER_THREAD_CNT	4
+#define MAX_SOCK_CLIENTS	80
+
+struct stun_test_session
+{
+    pj_stun_config	 stun_cfg;
+
+    pj_lock_t		*lock;
+
+    pj_thread_t		*worker_threads[WORKER_THREAD_CNT];
+
+    pj_sock_t		 server_sock;
+    int			 server_port;
+    pj_thread_t		*server_threads[SERVER_THREAD_CNT];
+    pj_event_t		*server_event;
+
+    pj_bool_t		 thread_quit_flag;
+
+    /* Test parameters:  */
+    struct {
+	int		 client_got_response;
+
+	pj_bool_t	 server_wait_for_event;
+	pj_bool_t	 server_drop_request;
+	int		 client_sleep_after_start;
+	int		 client_sleep_before_destroy;
+    } param;
+};
+
+static int server_thread_proc(void *p)
+{
+    struct stun_test_session *test_sess = (struct stun_test_session*)p;
+    pj_pool_t *pool;
+    pj_status_t status;
+
+    PJ_LOG(4,(THIS_FILE, "Server thread running"));
+
+    pool = pj_pool_create(test_sess->stun_cfg.pf, "server", 512, 512, NULL);
+
+    while (!test_sess->thread_quit_flag) {
+	pj_time_val timeout = {0, 10};
+	pj_fd_set_t rdset;
+	int n;
+
+	/* Serve client */
+	PJ_FD_ZERO(&rdset);
+	PJ_FD_SET(test_sess->server_sock, &rdset);
+	n = pj_sock_select((int)test_sess->server_sock+1, &rdset,
+	                   NULL, NULL, &timeout);
+	if (n==1 && PJ_FD_ISSET(test_sess->server_sock, &rdset)) {
+	    pj_uint8_t pkt[512];
+	    pj_ssize_t pkt_len;
+	    pj_size_t res_len;
+	    pj_sockaddr client_addr;
+	    int addr_len;
+
+	    pj_stun_msg	*stun_req, *stun_res;
+
+	    pj_pool_reset(pool);
+
+	    /* Got query */
+	    pkt_len = sizeof(pkt);
+	    addr_len = sizeof(client_addr);
+	    status = pj_sock_recvfrom(test_sess->server_sock, pkt, &pkt_len,
+	                              0, &client_addr, &addr_len);
+	    if (status != PJ_SUCCESS) {
+		continue;
+	    }
+
+	    status = pj_stun_msg_decode(pool, pkt, pkt_len,
+	                                PJ_STUN_IS_DATAGRAM,
+	                                &stun_req, NULL, NULL);
+	    if (status != PJ_SUCCESS) {
+		PJ_PERROR(1,(THIS_FILE, status, "STUN request decode error"));
+		continue;
+	    }
+
+	    status = pj_stun_msg_create_response(pool, stun_req,
+	                                         PJ_STUN_SC_BAD_REQUEST, NULL,
+	                                         &stun_res);
+	    if (status != PJ_SUCCESS) {
+		PJ_PERROR(1,(THIS_FILE, status, "STUN create response error"));
+		continue;
+	    }
+
+	    status = pj_stun_msg_encode(stun_res, pkt, sizeof(pkt), 0,
+	                                NULL, &res_len);
+	    if (status != PJ_SUCCESS) {
+		PJ_PERROR(1,(THIS_FILE, status, "STUN encode error"));
+		continue;
+	    }
+
+	    /* Ignore request */
+	    if (test_sess->param.server_drop_request)
+		continue;
+
+	    /* Wait for signal to continue */
+	    if (test_sess->param.server_wait_for_event)
+		pj_event_wait(test_sess->server_event);
+
+	    pkt_len = res_len;
+	    pj_sock_sendto(test_sess->server_sock, pkt, &pkt_len, 0,
+	                   &client_addr, pj_sockaddr_get_len(&client_addr));
+	}
+    }
+
+    pj_pool_release(pool);
+
+    PJ_LOG(4,(THIS_FILE, "Server thread quitting"));
+    return 0;
+}
+
+static int worker_thread_proc(void *p)
+{
+    struct stun_test_session *test_sess = (struct stun_test_session*)p;
+
+    PJ_LOG(4,(THIS_FILE, "Worker thread running"));
+
+    while (!test_sess->thread_quit_flag) {
+	pj_time_val timeout = {0, 10};
+	pj_timer_heap_poll(test_sess->stun_cfg.timer_heap, NULL);
+	pj_ioqueue_poll(test_sess->stun_cfg.ioqueue, &timeout);
+    }
+
+    PJ_LOG(4,(THIS_FILE, "Worker thread quitting"));
+    return 0;
+}
+
+static pj_bool_t stun_sock_on_status(pj_stun_sock *stun_sock,
+                                     pj_stun_sock_op op,
+                                     pj_status_t status)
+{
+    struct stun_test_session *test_sess = (struct stun_test_session*)pj_stun_sock_get_user_data(stun_sock);
+
+    PJ_UNUSED_ARG(op);
+    PJ_UNUSED_ARG(status);
+
+    test_sess->param.client_got_response++;
+    return PJ_TRUE;
+}
+
+static int stun_destroy_test_session(struct stun_test_session *test_sess)
+{
+
+    unsigned i;
+    pj_stun_sock_cb stun_cb;
+    pj_status_t status;
+    pj_stun_sock *stun_sock[MAX_SOCK_CLIENTS];
+
+    pj_bzero(&stun_cb, sizeof(stun_cb));
+    stun_cb.on_status = &stun_sock_on_status;
+
+    pj_event_reset(test_sess->server_event);
+
+    /* Create all clients first */
+    for (i=0; i<MAX_SOCK_CLIENTS; ++i) {
+	char name[10];
+	sprintf(name, "stun%02d", i);
+	status = pj_stun_sock_create(&test_sess->stun_cfg, name, pj_AF_INET(),
+	                             &stun_cb, NULL, test_sess,
+	                             &stun_sock[i]);
+	if (status != PJ_SUCCESS) {
+	    PJ_PERROR(1,(THIS_FILE, status, "Error creating stun socket"));
+	    return -10;
+	}
+    }
+
+    /* Start resolution */
+    for (i=0; i<MAX_SOCK_CLIENTS; ++i) {
+	pj_str_t server_ip = pj_str("127.0.0.1");
+	status = pj_stun_sock_start(stun_sock[i], &server_ip,
+	                            (pj_uint16_t)test_sess->server_port, NULL);
+	if (status != PJ_SUCCESS) {
+	    PJ_PERROR(1,(THIS_FILE, status, "Error starting stun socket"));
+	    return -20;
+	}
+    }
+
+    /* settle down */
+    pj_thread_sleep(test_sess->param.client_sleep_after_start);
+
+    /* Resume server threads */
+    pj_event_set(test_sess->server_event);
+
+    pj_thread_sleep(test_sess->param.client_sleep_before_destroy);
+
+    /* Destroy clients */
+    for (i=0; i<MAX_SOCK_CLIENTS; ++i) {
+	status = pj_stun_sock_destroy(stun_sock[i]);
+	if (status != PJ_SUCCESS) {
+	    PJ_PERROR(1,(THIS_FILE, status, "Error destroying stun socket"));
+	}
+    }
+
+    return 0;
+}
+
+static int stun_destroy_test(void)
+{
+    enum { LOOP = 500 };
+    struct stun_test_session test_sess;
+    pj_sockaddr bind_addr;
+    int addr_len;
+    pj_caching_pool cp;
+    pj_pool_t *pool;
+    unsigned i;
+    pj_status_t status;
+    int rc = 0;
+
+    PJ_LOG(3,(THIS_FILE, "  STUN destroy concurrency test"));
+
+    pj_bzero(&test_sess, sizeof(test_sess));
+
+    pj_caching_pool_init(&cp, NULL, 0);
+    pool = pj_pool_create(&cp.factory, "testsess", 512, 512, NULL);
+
+    pj_stun_config_init(&test_sess.stun_cfg, &cp.factory, 0, NULL, NULL);
+
+    status = pj_timer_heap_create(pool, 1023, &test_sess.stun_cfg.timer_heap);
+    pj_assert(status == PJ_SUCCESS);
+
+    status = pj_lock_create_recursive_mutex(pool, NULL, &test_sess.lock);
+    pj_assert(status == PJ_SUCCESS);
+
+    pj_timer_heap_set_lock(test_sess.stun_cfg.timer_heap, test_sess.lock, PJ_TRUE);
+    pj_assert(status == PJ_SUCCESS);
+
+    status = pj_ioqueue_create(pool, 512, &test_sess.stun_cfg.ioqueue);
+    pj_assert(status == PJ_SUCCESS);
+
+    pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &test_sess.server_sock);
+    pj_sockaddr_init(pj_AF_INET(), &bind_addr, NULL, 0);
+    status = pj_sock_bind(test_sess.server_sock, &bind_addr, pj_sockaddr_get_len(&bind_addr));
+    pj_assert(status == PJ_SUCCESS);
+
+    addr_len = sizeof(bind_addr);
+    status = pj_sock_getsockname(test_sess.server_sock, &bind_addr, &addr_len);
+    pj_assert(status == PJ_SUCCESS);
+
+    test_sess.server_port = pj_sockaddr_get_port(&bind_addr);
+
+    status = pj_event_create(pool, NULL, PJ_TRUE, PJ_FALSE, &test_sess.server_event);
+    pj_assert(status == PJ_SUCCESS);
+
+    for (i=0; i<SERVER_THREAD_CNT; ++i) {
+	status = pj_thread_create(pool, NULL,
+	                          &server_thread_proc, &test_sess,
+	                          0, 0, &test_sess.server_threads[i]);
+	pj_assert(status == PJ_SUCCESS);
+    }
+
+    for (i=0; i<WORKER_THREAD_CNT; ++i) {
+	status = pj_thread_create(pool, NULL,
+	                          &worker_thread_proc, &test_sess,
+	                          0, 0, &test_sess.worker_threads[i]);
+	pj_assert(status == PJ_SUCCESS);
+    }
+
+    /* Test 1: Main thread calls destroy while callback is processing response */
+    PJ_LOG(3,(THIS_FILE, "    Destroy in main thread while callback is running"));
+    for (i=0; i<LOOP; ++i) {
+	int sleep = pj_rand() % 5;
+
+	PJ_LOG(3,(THIS_FILE, "      Try %-3d of %d", i+1, LOOP));
+
+	/* Test 1: destroy at the same time when receiving response */
+	pj_bzero(&test_sess.param, sizeof(test_sess.param));
+	test_sess.param.client_sleep_after_start = 20;
+	test_sess.param.client_sleep_before_destroy = sleep;
+	test_sess.param.server_wait_for_event = PJ_TRUE;
+	stun_destroy_test_session(&test_sess);
+	PJ_LOG(3,(THIS_FILE,
+		  "        stun test a: sleep delay:%d: clients with response: %d",
+		  sleep, test_sess.param.client_got_response));
+
+	/* Test 2: destroy at the same time with STUN retransmit timer */
+	test_sess.param.server_drop_request = PJ_TRUE;
+	test_sess.param.client_sleep_after_start = 0;
+	test_sess.param.client_sleep_before_destroy = PJ_STUN_RTO_VALUE;
+	test_sess.param.server_wait_for_event = PJ_FALSE;
+	stun_destroy_test_session(&test_sess);
+	PJ_LOG(3,(THIS_FILE, "        stun test b: retransmit concurrency"));
+
+	/* Test 3: destroy at the same time with receiving response
+	 * AND STUN retransmit timer */
+	test_sess.param.client_got_response = 0;
+	test_sess.param.server_drop_request = PJ_FALSE;
+	test_sess.param.client_sleep_after_start = PJ_STUN_RTO_VALUE;
+	test_sess.param.client_sleep_before_destroy = 0;
+	test_sess.param.server_wait_for_event = PJ_TRUE;
+	stun_destroy_test_session(&test_sess);
+	PJ_LOG(3,(THIS_FILE,
+		  "        stun test c: clients with response: %d",
+		  test_sess.param.client_got_response));
+
+	pj_thread_sleep(10);
+
+	ice_one_conc_test(&test_sess.stun_cfg, PJ_FALSE);
+
+	pj_thread_sleep(10);
+    }
+
+    /* Avoid compiler warning */
+    goto on_return;
+
+
+on_return:
+    test_sess.thread_quit_flag = PJ_TRUE;
+
+    for (i=0; i<SERVER_THREAD_CNT; ++i) {
+	pj_thread_join(test_sess.server_threads[i]);
+    }
+
+    for (i=0; i<WORKER_THREAD_CNT; ++i) {
+	pj_thread_join(test_sess.worker_threads[i]);
+    }
+
+    pj_event_destroy(test_sess.server_event);
+    pj_sock_close(test_sess.server_sock);
+    pj_ioqueue_destroy(test_sess.stun_cfg.ioqueue);
+    pj_timer_heap_destroy(test_sess.stun_cfg.timer_heap);
+
+    pj_pool_release(pool);
+    pj_caching_pool_destroy(&cp);
+
+    PJ_LOG(3,(THIS_FILE, "    Done. rc=%d", rc));
+    return rc;
+}
+
+
+int concur_test(void)
+{
+    int rc = 0;
+
+    rc += stun_destroy_test();
+
+    return 0;
+}
+
+#endif	/* INCLUDE_CONCUR_TEST */
diff --git a/jni/pjproject-android/.svn/pristine/36/36305041a9e1f31c430ae0bd4ffbd2136547814f.svn-base b/jni/pjproject-android/.svn/pristine/36/36305041a9e1f31c430ae0bd4ffbd2136547814f.svn-base
new file mode 100644
index 0000000..4529fad
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/36/36305041a9e1f31c430ae0bd4ffbd2136547814f.svn-base
@@ -0,0 +1,173 @@
+/* $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 <stdlib.h>	/* strtol() */
+
+/* Util to display the error message for the specified error code  */
+static int app_perror( const char *sender, const char *title, 
+		       pj_status_t status)
+{
+    char errmsg[PJ_ERR_MSG_SIZE];
+
+    pj_strerror(status, errmsg, sizeof(errmsg));
+
+    PJ_LOG(3,(sender, "%s: %s [code=%d]", title, errmsg, status));
+    return 1;
+}
+
+
+
+/* Constants */
+#define CLOCK_RATE	44100
+#define NSAMPLES	(CLOCK_RATE * 20 / 1000)
+#define NCHANNELS	1
+#define NBITS		16
+
+/*
+ * Common sound options.
+ */
+#define SND_USAGE   \
+"  -d, --dev=NUM        Sound device use device id NUM (default=-1)	 \n"\
+"  -r, --rate=HZ        Set clock rate in samples per sec (default=44100)\n"\
+"  -c, --channel=NUM    Set # of channels (default=1 for mono).		 \n"\
+"  -f, --frame=NUM      Set # of samples per frame (default equival 20ms)\n"\
+"  -b, --bit=NUM        Set # of bits per sample (default=16)		 \n"
+
+
+/*
+ * This utility function parses the command line and look for
+ * common sound options.
+ */
+pj_status_t get_snd_options(const char *app_name,
+			    int argc, 
+			    char *argv[],
+			    int *dev_id,
+			    int *clock_rate,
+			    int *channel_count,
+			    int *samples_per_frame,
+			    int *bits_per_sample)
+{
+    struct pj_getopt_option long_options[] = {
+	{ "dev",	1, 0, 'd' },
+	{ "rate",	1, 0, 'r' },
+	{ "channel",	1, 0, 'c' },
+	{ "frame",	1, 0, 'f' },
+	{ "bit",	1, 0, 'b' },
+	{ NULL, 0, 0, 0 },
+    };
+    int c;
+    int option_index;
+    long val;
+    char *err;
+
+    *samples_per_frame = 0;
+
+    pj_optind = 0;
+    while((c=pj_getopt_long(argc,argv, "d:r:c:f:b:", 
+			    long_options, &option_index))!=-1) 
+    {
+
+	switch (c) {
+	case 'd':
+	    /* device */
+	    val = strtol(pj_optarg, &err, 10);
+	    if (*err) {
+		PJ_LOG(3,(app_name, "Error: invalid value for device id"));
+		return PJ_EINVAL;
+	    }
+	    *dev_id = val;
+	    break;
+
+	case 'r':
+	    /* rate */
+	    val = strtol(pj_optarg, &err, 10);
+	    if (*err) {
+		PJ_LOG(3,(app_name, "Error: invalid value for clock rate"));
+		return PJ_EINVAL;
+	    }
+	    *clock_rate = val;
+	    break;
+
+	case 'c':
+	    /* channel count */
+	    val = strtol(pj_optarg, &err, 10);
+	    if (*err) {
+		PJ_LOG(3,(app_name, "Error: invalid channel count"));
+		return PJ_EINVAL;
+	    }
+	    *channel_count = val;
+	    break;
+
+	case 'f':
+	    /* frame count/samples per frame */
+	    val = strtol(pj_optarg, &err, 10);
+	    if (*err) {
+		PJ_LOG(3,(app_name, "Error: invalid samples per frame"));
+		return PJ_EINVAL;
+	    }
+	    *samples_per_frame = val;
+	    break;
+
+	case 'b':
+	    /* bit per sample */
+	    val = strtol(pj_optarg, &err, 10);
+	    if (*err) {
+		PJ_LOG(3,(app_name, "Error: invalid samples bits per sample"));
+		return PJ_EINVAL;
+	    }
+	    *bits_per_sample = val;
+	    break;
+
+	default:
+	    /* Unknown options */
+	    PJ_LOG(3,(app_name, "Error: unknown options '%c'", pj_optopt));
+	    return PJ_EINVAL;
+	}
+
+    }
+
+    if (*samples_per_frame == 0) {
+	*samples_per_frame = *clock_rate * *channel_count * 20 / 1000;
+    }
+
+    return 0;
+}
+
+
+/* Dump memory pool usage. */
+void dump_pool_usage( const char *app_name, pj_caching_pool *cp )
+{
+#if !defined(PJ_HAS_POOL_ALT_API) || PJ_HAS_POOL_ALT_API==0
+    pj_pool_t   *p;
+    pj_size_t    total_alloc = 0;
+    pj_size_t    total_used = 0;
+
+    /* Accumulate memory usage in active list. */
+    p = cp->used_list.next;
+    while (p != (pj_pool_t*) &cp->used_list) {
+	total_alloc += pj_pool_get_capacity(p);
+	total_used += pj_pool_get_used_size(p);
+	p = p->next;
+    }
+
+    PJ_LOG(3, (app_name, "Total pool memory allocated=%d KB, used=%d KB",
+	       total_alloc / 1000,
+	       total_used / 1000));
+#endif
+}
diff --git a/jni/pjproject-android/.svn/pristine/36/364b4d715e5eada3c9ab29a586a3ce2ca651361f.svn-base b/jni/pjproject-android/.svn/pristine/36/364b4d715e5eada3c9ab29a586a3ce2ca651361f.svn-base
new file mode 100644
index 0000000..d26605a
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/36/364b4d715e5eada3c9ab29a586a3ce2ca651361f.svn-base
@@ -0,0 +1,12 @@
+
+/* 
+ *  !! OIY OIY !!
+ *
+ *  The purpose of this file is only to get the executable linked. I haven't
+ *  actually tried to run this on RTEMS!!
+ *
+ */
+
+#include "../../pjlib/src/pjlib-test/main_rtems.c"
+
+
diff --git a/jni/pjproject-android/.svn/pristine/36/3650bfdf9f8fc0da531faac7bb4468338a5a8830.svn-base b/jni/pjproject-android/.svn/pristine/36/3650bfdf9f8fc0da531faac7bb4468338a5a8830.svn-base
new file mode 100644
index 0000000..e320527
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/36/3650bfdf9f8fc0da531faac7bb4468338a5a8830.svn-base
Binary files differ
diff --git a/jni/pjproject-android/.svn/pristine/36/365cde1a3491bd53b424a6d3b731ee3effab3d2e.svn-base b/jni/pjproject-android/.svn/pristine/36/365cde1a3491bd53b424a6d3b731ee3effab3d2e.svn-base
new file mode 100644
index 0000000..3cfc611
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/36/365cde1a3491bd53b424a6d3b731ee3effab3d2e.svn-base
@@ -0,0 +1,27 @@
+# $Id$
+import inc_sip as sip
+import inc_sdp as sdp
+
+# Multiple m=audio, one of them is bad
+sdp = \
+"""
+v=0
+o=- 0 0 IN IP4 127.0.0.1
+s=-
+c=IN IP4 127.0.0.1
+t=0 0
+m=audio 5000 RTP/AVP 0
+m=audio 4000 UNKNOWN 0
+"""
+
+pjsua_args = "--null-audio --auto-answer 200"
+extra_headers = ""
+include = ["Content-Type: application/sdp",	# response must include SDP
+	   "m=audio [1-9]+[0-9]* RTP/AVP[\\s\\S]+m=audio 0 UNKNOWN"
+	   ]
+exclude = []
+
+sendto_cfg = sip.SendtoCfg("Audio and bad audio", pjsua_args, sdp, 200,
+			   extra_headers=extra_headers,
+			   resp_inc=include, resp_exc=exclude) 
+
diff --git a/jni/pjproject-android/.svn/pristine/36/36620d9e869db3df8d6e9a4f0080ec5adc3e573a.svn-base b/jni/pjproject-android/.svn/pristine/36/36620d9e869db3df8d6e9a4f0080ec5adc3e573a.svn-base
new file mode 100644
index 0000000..a397dc5
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/36/36620d9e869db3df8d6e9a4f0080ec5adc3e573a.svn-base
@@ -0,0 +1,1261 @@
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
+ *                                                                  *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
+ * by the XIPHOPHORUS Company http://www.xiph.org/                  *
+ *                                                                  *
+ ********************************************************************
+
+ function: *unnormalized* fft transform
+ last mod: $Id$
+
+ ********************************************************************/
+
+/* FFT implementation from OggSquish, minus cosine transforms,
+ * minus all but radix 2/4 case.  In Vorbis we only need this
+ * cut-down version.
+ *
+ * To do more than just power-of-two sized vectors, see the full
+ * version I wrote for NetLib.
+ *
+ * Note that the packing is a little strange; rather than the FFT r/i
+ * packing following R_0, I_n, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1,
+ * it follows R_0, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1, I_n like the
+ * FORTRAN version
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include "smallft.h"
+#include "arch.h"
+#include "os_support.h"
+
+static void drfti1(int n, float *wa, int *ifac){
+  static int ntryh[4] = { 4,2,3,5 };
+  static float tpi = 6.28318530717958648f;
+  float arg,argh,argld,fi;
+  int ntry=0,i,j=-1;
+  int k1, l1, l2, ib;
+  int ld, ii, ip, is, nq, nr;
+  int ido, ipm, nfm1;
+  int nl=n;
+  int nf=0;
+
+ L101:
+  j++;
+  if (j < 4)
+    ntry=ntryh[j];
+  else
+    ntry+=2;
+
+ L104:
+  nq=nl/ntry;
+  nr=nl-ntry*nq;
+  if (nr!=0) goto L101;
+
+  nf++;
+  ifac[nf+1]=ntry;
+  nl=nq;
+  if(ntry!=2)goto L107;
+  if(nf==1)goto L107;
+
+  for (i=1;i<nf;i++){
+    ib=nf-i+1;
+    ifac[ib+1]=ifac[ib];
+  }
+  ifac[2] = 2;
+
+ L107:
+  if(nl!=1)goto L104;
+  ifac[0]=n;
+  ifac[1]=nf;
+  argh=tpi/n;
+  is=0;
+  nfm1=nf-1;
+  l1=1;
+
+  if(nfm1==0)return;
+
+  for (k1=0;k1<nfm1;k1++){
+    ip=ifac[k1+2];
+    ld=0;
+    l2=l1*ip;
+    ido=n/l2;
+    ipm=ip-1;
+
+    for (j=0;j<ipm;j++){
+      ld+=l1;
+      i=is;
+      argld=(float)ld*argh;
+      fi=0.f;
+      for (ii=2;ii<ido;ii+=2){
+	fi+=1.f;
+	arg=fi*argld;
+	wa[i++]=cos(arg);
+	wa[i++]=sin(arg);
+      }
+      is+=ido;
+    }
+    l1=l2;
+  }
+}
+
+static void fdrffti(int n, float *wsave, int *ifac){
+
+  if (n == 1) return;
+  drfti1(n, wsave+n, ifac);
+}
+
+static void dradf2(int ido,int l1,float *cc,float *ch,float *wa1){
+  int i,k;
+  float ti2,tr2;
+  int t0,t1,t2,t3,t4,t5,t6;
+
+  t1=0;
+  t0=(t2=l1*ido);
+  t3=ido<<1;
+  for(k=0;k<l1;k++){
+    ch[t1<<1]=cc[t1]+cc[t2];
+    ch[(t1<<1)+t3-1]=cc[t1]-cc[t2];
+    t1+=ido;
+    t2+=ido;
+  }
+    
+  if(ido<2)return;
+  if(ido==2)goto L105;
+
+  t1=0;
+  t2=t0;
+  for(k=0;k<l1;k++){
+    t3=t2;
+    t4=(t1<<1)+(ido<<1);
+    t5=t1;
+    t6=t1+t1;
+    for(i=2;i<ido;i+=2){
+      t3+=2;
+      t4-=2;
+      t5+=2;
+      t6+=2;
+      tr2=wa1[i-2]*cc[t3-1]+wa1[i-1]*cc[t3];
+      ti2=wa1[i-2]*cc[t3]-wa1[i-1]*cc[t3-1];
+      ch[t6]=cc[t5]+ti2;
+      ch[t4]=ti2-cc[t5];
+      ch[t6-1]=cc[t5-1]+tr2;
+      ch[t4-1]=cc[t5-1]-tr2;
+    }
+    t1+=ido;
+    t2+=ido;
+  }
+
+  if(ido%2==1)return;
+
+ L105:
+  t3=(t2=(t1=ido)-1);
+  t2+=t0;
+  for(k=0;k<l1;k++){
+    ch[t1]=-cc[t2];
+    ch[t1-1]=cc[t3];
+    t1+=ido<<1;
+    t2+=ido;
+    t3+=ido;
+  }
+}
+
+static void dradf4(int ido,int l1,float *cc,float *ch,float *wa1,
+	    float *wa2,float *wa3){
+  static float hsqt2 = .70710678118654752f;
+  int i,k,t0,t1,t2,t3,t4,t5,t6;
+  float ci2,ci3,ci4,cr2,cr3,cr4,ti1,ti2,ti3,ti4,tr1,tr2,tr3,tr4;
+  t0=l1*ido;
+  
+  t1=t0;
+  t4=t1<<1;
+  t2=t1+(t1<<1);
+  t3=0;
+
+  for(k=0;k<l1;k++){
+    tr1=cc[t1]+cc[t2];
+    tr2=cc[t3]+cc[t4];
+
+    ch[t5=t3<<2]=tr1+tr2;
+    ch[(ido<<2)+t5-1]=tr2-tr1;
+    ch[(t5+=(ido<<1))-1]=cc[t3]-cc[t4];
+    ch[t5]=cc[t2]-cc[t1];
+
+    t1+=ido;
+    t2+=ido;
+    t3+=ido;
+    t4+=ido;
+  }
+
+  if(ido<2)return;
+  if(ido==2)goto L105;
+
+
+  t1=0;
+  for(k=0;k<l1;k++){
+    t2=t1;
+    t4=t1<<2;
+    t5=(t6=ido<<1)+t4;
+    for(i=2;i<ido;i+=2){
+      t3=(t2+=2);
+      t4+=2;
+      t5-=2;
+
+      t3+=t0;
+      cr2=wa1[i-2]*cc[t3-1]+wa1[i-1]*cc[t3];
+      ci2=wa1[i-2]*cc[t3]-wa1[i-1]*cc[t3-1];
+      t3+=t0;
+      cr3=wa2[i-2]*cc[t3-1]+wa2[i-1]*cc[t3];
+      ci3=wa2[i-2]*cc[t3]-wa2[i-1]*cc[t3-1];
+      t3+=t0;
+      cr4=wa3[i-2]*cc[t3-1]+wa3[i-1]*cc[t3];
+      ci4=wa3[i-2]*cc[t3]-wa3[i-1]*cc[t3-1];
+
+      tr1=cr2+cr4;
+      tr4=cr4-cr2;
+      ti1=ci2+ci4;
+      ti4=ci2-ci4;
+
+      ti2=cc[t2]+ci3;
+      ti3=cc[t2]-ci3;
+      tr2=cc[t2-1]+cr3;
+      tr3=cc[t2-1]-cr3;
+
+      ch[t4-1]=tr1+tr2;
+      ch[t4]=ti1+ti2;
+
+      ch[t5-1]=tr3-ti4;
+      ch[t5]=tr4-ti3;
+
+      ch[t4+t6-1]=ti4+tr3;
+      ch[t4+t6]=tr4+ti3;
+
+      ch[t5+t6-1]=tr2-tr1;
+      ch[t5+t6]=ti1-ti2;
+    }
+    t1+=ido;
+  }
+  if(ido&1)return;
+
+ L105:
+  
+  t2=(t1=t0+ido-1)+(t0<<1);
+  t3=ido<<2;
+  t4=ido;
+  t5=ido<<1;
+  t6=ido;
+
+  for(k=0;k<l1;k++){
+    ti1=-hsqt2*(cc[t1]+cc[t2]);
+    tr1=hsqt2*(cc[t1]-cc[t2]);
+
+    ch[t4-1]=tr1+cc[t6-1];
+    ch[t4+t5-1]=cc[t6-1]-tr1;
+
+    ch[t4]=ti1-cc[t1+t0];
+    ch[t4+t5]=ti1+cc[t1+t0];
+
+    t1+=ido;
+    t2+=ido;
+    t4+=t3;
+    t6+=ido;
+  }
+}
+
+static void dradfg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
+                          float *c2,float *ch,float *ch2,float *wa){
+
+  static float tpi=6.283185307179586f;
+  int idij,ipph,i,j,k,l,ic,ik,is;
+  int t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
+  float dc2,ai1,ai2,ar1,ar2,ds2;
+  int nbd;
+  float dcp,arg,dsp,ar1h,ar2h;
+  int idp2,ipp2;
+  
+  arg=tpi/(float)ip;
+  dcp=cos(arg);
+  dsp=sin(arg);
+  ipph=(ip+1)>>1;
+  ipp2=ip;
+  idp2=ido;
+  nbd=(ido-1)>>1;
+  t0=l1*ido;
+  t10=ip*ido;
+
+  if(ido==1)goto L119;
+  for(ik=0;ik<idl1;ik++)ch2[ik]=c2[ik];
+
+  t1=0;
+  for(j=1;j<ip;j++){
+    t1+=t0;
+    t2=t1;
+    for(k=0;k<l1;k++){
+      ch[t2]=c1[t2];
+      t2+=ido;
+    }
+  }
+
+  is=-ido;
+  t1=0;
+  if(nbd>l1){
+    for(j=1;j<ip;j++){
+      t1+=t0;
+      is+=ido;
+      t2= -ido+t1;
+      for(k=0;k<l1;k++){
+        idij=is-1;
+        t2+=ido;
+        t3=t2;
+        for(i=2;i<ido;i+=2){
+          idij+=2;
+          t3+=2;
+          ch[t3-1]=wa[idij-1]*c1[t3-1]+wa[idij]*c1[t3];
+          ch[t3]=wa[idij-1]*c1[t3]-wa[idij]*c1[t3-1];
+        }
+      }
+    }
+  }else{
+
+    for(j=1;j<ip;j++){
+      is+=ido;
+      idij=is-1;
+      t1+=t0;
+      t2=t1;
+      for(i=2;i<ido;i+=2){
+        idij+=2;
+        t2+=2;
+        t3=t2;
+        for(k=0;k<l1;k++){
+          ch[t3-1]=wa[idij-1]*c1[t3-1]+wa[idij]*c1[t3];
+          ch[t3]=wa[idij-1]*c1[t3]-wa[idij]*c1[t3-1];
+          t3+=ido;
+        }
+      }
+    }
+  }
+
+  t1=0;
+  t2=ipp2*t0;
+  if(nbd<l1){
+    for(j=1;j<ipph;j++){
+      t1+=t0;
+      t2-=t0;
+      t3=t1;
+      t4=t2;
+      for(i=2;i<ido;i+=2){
+        t3+=2;
+        t4+=2;
+        t5=t3-ido;
+        t6=t4-ido;
+        for(k=0;k<l1;k++){
+          t5+=ido;
+          t6+=ido;
+          c1[t5-1]=ch[t5-1]+ch[t6-1];
+          c1[t6-1]=ch[t5]-ch[t6];
+          c1[t5]=ch[t5]+ch[t6];
+          c1[t6]=ch[t6-1]-ch[t5-1];
+        }
+      }
+    }
+  }else{
+    for(j=1;j<ipph;j++){
+      t1+=t0;
+      t2-=t0;
+      t3=t1;
+      t4=t2;
+      for(k=0;k<l1;k++){
+        t5=t3;
+        t6=t4;
+        for(i=2;i<ido;i+=2){
+          t5+=2;
+          t6+=2;
+          c1[t5-1]=ch[t5-1]+ch[t6-1];
+          c1[t6-1]=ch[t5]-ch[t6];
+          c1[t5]=ch[t5]+ch[t6];
+          c1[t6]=ch[t6-1]-ch[t5-1];
+        }
+        t3+=ido;
+        t4+=ido;
+      }
+    }
+  }
+
+L119:
+  for(ik=0;ik<idl1;ik++)c2[ik]=ch2[ik];
+
+  t1=0;
+  t2=ipp2*idl1;
+  for(j=1;j<ipph;j++){
+    t1+=t0;
+    t2-=t0;
+    t3=t1-ido;
+    t4=t2-ido;
+    for(k=0;k<l1;k++){
+      t3+=ido;
+      t4+=ido;
+      c1[t3]=ch[t3]+ch[t4];
+      c1[t4]=ch[t4]-ch[t3];
+    }
+  }
+
+  ar1=1.f;
+  ai1=0.f;
+  t1=0;
+  t2=ipp2*idl1;
+  t3=(ip-1)*idl1;
+  for(l=1;l<ipph;l++){
+    t1+=idl1;
+    t2-=idl1;
+    ar1h=dcp*ar1-dsp*ai1;
+    ai1=dcp*ai1+dsp*ar1;
+    ar1=ar1h;
+    t4=t1;
+    t5=t2;
+    t6=t3;
+    t7=idl1;
+
+    for(ik=0;ik<idl1;ik++){
+      ch2[t4++]=c2[ik]+ar1*c2[t7++];
+      ch2[t5++]=ai1*c2[t6++];
+    }
+
+    dc2=ar1;
+    ds2=ai1;
+    ar2=ar1;
+    ai2=ai1;
+
+    t4=idl1;
+    t5=(ipp2-1)*idl1;
+    for(j=2;j<ipph;j++){
+      t4+=idl1;
+      t5-=idl1;
+
+      ar2h=dc2*ar2-ds2*ai2;
+      ai2=dc2*ai2+ds2*ar2;
+      ar2=ar2h;
+
+      t6=t1;
+      t7=t2;
+      t8=t4;
+      t9=t5;
+      for(ik=0;ik<idl1;ik++){
+        ch2[t6++]+=ar2*c2[t8++];
+        ch2[t7++]+=ai2*c2[t9++];
+      }
+    }
+  }
+
+  t1=0;
+  for(j=1;j<ipph;j++){
+    t1+=idl1;
+    t2=t1;
+    for(ik=0;ik<idl1;ik++)ch2[ik]+=c2[t2++];
+  }
+
+  if(ido<l1)goto L132;
+
+  t1=0;
+  t2=0;
+  for(k=0;k<l1;k++){
+    t3=t1;
+    t4=t2;
+    for(i=0;i<ido;i++)cc[t4++]=ch[t3++];
+    t1+=ido;
+    t2+=t10;
+  }
+
+  goto L135;
+
+ L132:
+  for(i=0;i<ido;i++){
+    t1=i;
+    t2=i;
+    for(k=0;k<l1;k++){
+      cc[t2]=ch[t1];
+      t1+=ido;
+      t2+=t10;
+    }
+  }
+
+ L135:
+  t1=0;
+  t2=ido<<1;
+  t3=0;
+  t4=ipp2*t0;
+  for(j=1;j<ipph;j++){
+
+    t1+=t2;
+    t3+=t0;
+    t4-=t0;
+
+    t5=t1;
+    t6=t3;
+    t7=t4;
+
+    for(k=0;k<l1;k++){
+      cc[t5-1]=ch[t6];
+      cc[t5]=ch[t7];
+      t5+=t10;
+      t6+=ido;
+      t7+=ido;
+    }
+  }
+
+  if(ido==1)return;
+  if(nbd<l1)goto L141;
+
+  t1=-ido;
+  t3=0;
+  t4=0;
+  t5=ipp2*t0;
+  for(j=1;j<ipph;j++){
+    t1+=t2;
+    t3+=t2;
+    t4+=t0;
+    t5-=t0;
+    t6=t1;
+    t7=t3;
+    t8=t4;
+    t9=t5;
+    for(k=0;k<l1;k++){
+      for(i=2;i<ido;i+=2){
+        ic=idp2-i;
+        cc[i+t7-1]=ch[i+t8-1]+ch[i+t9-1];
+        cc[ic+t6-1]=ch[i+t8-1]-ch[i+t9-1];
+        cc[i+t7]=ch[i+t8]+ch[i+t9];
+        cc[ic+t6]=ch[i+t9]-ch[i+t8];
+      }
+      t6+=t10;
+      t7+=t10;
+      t8+=ido;
+      t9+=ido;
+    }
+  }
+  return;
+
+ L141:
+
+  t1=-ido;
+  t3=0;
+  t4=0;
+  t5=ipp2*t0;
+  for(j=1;j<ipph;j++){
+    t1+=t2;
+    t3+=t2;
+    t4+=t0;
+    t5-=t0;
+    for(i=2;i<ido;i+=2){
+      t6=idp2+t1-i;
+      t7=i+t3;
+      t8=i+t4;
+      t9=i+t5;
+      for(k=0;k<l1;k++){
+        cc[t7-1]=ch[t8-1]+ch[t9-1];
+        cc[t6-1]=ch[t8-1]-ch[t9-1];
+        cc[t7]=ch[t8]+ch[t9];
+        cc[t6]=ch[t9]-ch[t8];
+        t6+=t10;
+        t7+=t10;
+        t8+=ido;
+        t9+=ido;
+      }
+    }
+  }
+}
+
+static void drftf1(int n,float *c,float *ch,float *wa,int *ifac){
+  int i,k1,l1,l2;
+  int na,kh,nf;
+  int ip,iw,ido,idl1,ix2,ix3;
+
+  nf=ifac[1];
+  na=1;
+  l2=n;
+  iw=n;
+
+  for(k1=0;k1<nf;k1++){
+    kh=nf-k1;
+    ip=ifac[kh+1];
+    l1=l2/ip;
+    ido=n/l2;
+    idl1=ido*l1;
+    iw-=(ip-1)*ido;
+    na=1-na;
+
+    if(ip!=4)goto L102;
+
+    ix2=iw+ido;
+    ix3=ix2+ido;
+    if(na!=0)
+      dradf4(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1);
+    else
+      dradf4(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1);
+    goto L110;
+
+ L102:
+    if(ip!=2)goto L104;
+    if(na!=0)goto L103;
+
+    dradf2(ido,l1,c,ch,wa+iw-1);
+    goto L110;
+
+  L103:
+    dradf2(ido,l1,ch,c,wa+iw-1);
+    goto L110;
+
+  L104:
+    if(ido==1)na=1-na;
+    if(na!=0)goto L109;
+
+    dradfg(ido,ip,l1,idl1,c,c,c,ch,ch,wa+iw-1);
+    na=1;
+    goto L110;
+
+  L109:
+    dradfg(ido,ip,l1,idl1,ch,ch,ch,c,c,wa+iw-1);
+    na=0;
+
+  L110:
+    l2=l1;
+  }
+
+  if(na==1)return;
+
+  for(i=0;i<n;i++)c[i]=ch[i];
+}
+
+static void dradb2(int ido,int l1,float *cc,float *ch,float *wa1){
+  int i,k,t0,t1,t2,t3,t4,t5,t6;
+  float ti2,tr2;
+
+  t0=l1*ido;
+  
+  t1=0;
+  t2=0;
+  t3=(ido<<1)-1;
+  for(k=0;k<l1;k++){
+    ch[t1]=cc[t2]+cc[t3+t2];
+    ch[t1+t0]=cc[t2]-cc[t3+t2];
+    t2=(t1+=ido)<<1;
+  }
+
+  if(ido<2)return;
+  if(ido==2)goto L105;
+
+  t1=0;
+  t2=0;
+  for(k=0;k<l1;k++){
+    t3=t1;
+    t5=(t4=t2)+(ido<<1);
+    t6=t0+t1;
+    for(i=2;i<ido;i+=2){
+      t3+=2;
+      t4+=2;
+      t5-=2;
+      t6+=2;
+      ch[t3-1]=cc[t4-1]+cc[t5-1];
+      tr2=cc[t4-1]-cc[t5-1];
+      ch[t3]=cc[t4]-cc[t5];
+      ti2=cc[t4]+cc[t5];
+      ch[t6-1]=wa1[i-2]*tr2-wa1[i-1]*ti2;
+      ch[t6]=wa1[i-2]*ti2+wa1[i-1]*tr2;
+    }
+    t2=(t1+=ido)<<1;
+  }
+
+  if(ido%2==1)return;
+
+L105:
+  t1=ido-1;
+  t2=ido-1;
+  for(k=0;k<l1;k++){
+    ch[t1]=cc[t2]+cc[t2];
+    ch[t1+t0]=-(cc[t2+1]+cc[t2+1]);
+    t1+=ido;
+    t2+=ido<<1;
+  }
+}
+
+static void dradb3(int ido,int l1,float *cc,float *ch,float *wa1,
+                          float *wa2){
+  static float taur = -.5f;
+  static float taui = .8660254037844386f;
+  int i,k,t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
+  float ci2,ci3,di2,di3,cr2,cr3,dr2,dr3,ti2,tr2;
+  t0=l1*ido;
+
+  t1=0;
+  t2=t0<<1;
+  t3=ido<<1;
+  t4=ido+(ido<<1);
+  t5=0;
+  for(k=0;k<l1;k++){
+    tr2=cc[t3-1]+cc[t3-1];
+    cr2=cc[t5]+(taur*tr2);
+    ch[t1]=cc[t5]+tr2;
+    ci3=taui*(cc[t3]+cc[t3]);
+    ch[t1+t0]=cr2-ci3;
+    ch[t1+t2]=cr2+ci3;
+    t1+=ido;
+    t3+=t4;
+    t5+=t4;
+  }
+
+  if(ido==1)return;
+
+  t1=0;
+  t3=ido<<1;
+  for(k=0;k<l1;k++){
+    t7=t1+(t1<<1);
+    t6=(t5=t7+t3);
+    t8=t1;
+    t10=(t9=t1+t0)+t0;
+
+    for(i=2;i<ido;i+=2){
+      t5+=2;
+      t6-=2;
+      t7+=2;
+      t8+=2;
+      t9+=2;
+      t10+=2;
+      tr2=cc[t5-1]+cc[t6-1];
+      cr2=cc[t7-1]+(taur*tr2);
+      ch[t8-1]=cc[t7-1]+tr2;
+      ti2=cc[t5]-cc[t6];
+      ci2=cc[t7]+(taur*ti2);
+      ch[t8]=cc[t7]+ti2;
+      cr3=taui*(cc[t5-1]-cc[t6-1]);
+      ci3=taui*(cc[t5]+cc[t6]);
+      dr2=cr2-ci3;
+      dr3=cr2+ci3;
+      di2=ci2+cr3;
+      di3=ci2-cr3;
+      ch[t9-1]=wa1[i-2]*dr2-wa1[i-1]*di2;
+      ch[t9]=wa1[i-2]*di2+wa1[i-1]*dr2;
+      ch[t10-1]=wa2[i-2]*dr3-wa2[i-1]*di3;
+      ch[t10]=wa2[i-2]*di3+wa2[i-1]*dr3;
+    }
+    t1+=ido;
+  }
+}
+
+static void dradb4(int ido,int l1,float *cc,float *ch,float *wa1,
+			  float *wa2,float *wa3){
+  static float sqrt2=1.414213562373095f;
+  int i,k,t0,t1,t2,t3,t4,t5,t6,t7,t8;
+  float ci2,ci3,ci4,cr2,cr3,cr4,ti1,ti2,ti3,ti4,tr1,tr2,tr3,tr4;
+  t0=l1*ido;
+  
+  t1=0;
+  t2=ido<<2;
+  t3=0;
+  t6=ido<<1;
+  for(k=0;k<l1;k++){
+    t4=t3+t6;
+    t5=t1;
+    tr3=cc[t4-1]+cc[t4-1];
+    tr4=cc[t4]+cc[t4]; 
+    tr1=cc[t3]-cc[(t4+=t6)-1];
+    tr2=cc[t3]+cc[t4-1];
+    ch[t5]=tr2+tr3;
+    ch[t5+=t0]=tr1-tr4;
+    ch[t5+=t0]=tr2-tr3;
+    ch[t5+=t0]=tr1+tr4;
+    t1+=ido;
+    t3+=t2;
+  }
+
+  if(ido<2)return;
+  if(ido==2)goto L105;
+
+  t1=0;
+  for(k=0;k<l1;k++){
+    t5=(t4=(t3=(t2=t1<<2)+t6))+t6;
+    t7=t1;
+    for(i=2;i<ido;i+=2){
+      t2+=2;
+      t3+=2;
+      t4-=2;
+      t5-=2;
+      t7+=2;
+      ti1=cc[t2]+cc[t5];
+      ti2=cc[t2]-cc[t5];
+      ti3=cc[t3]-cc[t4];
+      tr4=cc[t3]+cc[t4];
+      tr1=cc[t2-1]-cc[t5-1];
+      tr2=cc[t2-1]+cc[t5-1];
+      ti4=cc[t3-1]-cc[t4-1];
+      tr3=cc[t3-1]+cc[t4-1];
+      ch[t7-1]=tr2+tr3;
+      cr3=tr2-tr3;
+      ch[t7]=ti2+ti3;
+      ci3=ti2-ti3;
+      cr2=tr1-tr4;
+      cr4=tr1+tr4;
+      ci2=ti1+ti4;
+      ci4=ti1-ti4;
+
+      ch[(t8=t7+t0)-1]=wa1[i-2]*cr2-wa1[i-1]*ci2;
+      ch[t8]=wa1[i-2]*ci2+wa1[i-1]*cr2;
+      ch[(t8+=t0)-1]=wa2[i-2]*cr3-wa2[i-1]*ci3;
+      ch[t8]=wa2[i-2]*ci3+wa2[i-1]*cr3;
+      ch[(t8+=t0)-1]=wa3[i-2]*cr4-wa3[i-1]*ci4;
+      ch[t8]=wa3[i-2]*ci4+wa3[i-1]*cr4;
+    }
+    t1+=ido;
+  }
+
+  if(ido%2 == 1)return;
+
+ L105:
+
+  t1=ido;
+  t2=ido<<2;
+  t3=ido-1;
+  t4=ido+(ido<<1);
+  for(k=0;k<l1;k++){
+    t5=t3;
+    ti1=cc[t1]+cc[t4];
+    ti2=cc[t4]-cc[t1];
+    tr1=cc[t1-1]-cc[t4-1];
+    tr2=cc[t1-1]+cc[t4-1];
+    ch[t5]=tr2+tr2;
+    ch[t5+=t0]=sqrt2*(tr1-ti1);
+    ch[t5+=t0]=ti2+ti2;
+    ch[t5+=t0]=-sqrt2*(tr1+ti1);
+
+    t3+=ido;
+    t1+=t2;
+    t4+=t2;
+  }
+}
+
+static void dradbg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
+            float *c2,float *ch,float *ch2,float *wa){
+  static float tpi=6.283185307179586f;
+  int idij,ipph,i,j,k,l,ik,is,t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,
+      t11,t12;
+  float dc2,ai1,ai2,ar1,ar2,ds2;
+  int nbd;
+  float dcp,arg,dsp,ar1h,ar2h;
+  int ipp2;
+
+  t10=ip*ido;
+  t0=l1*ido;
+  arg=tpi/(float)ip;
+  dcp=cos(arg);
+  dsp=sin(arg);
+  nbd=(ido-1)>>1;
+  ipp2=ip;
+  ipph=(ip+1)>>1;
+  if(ido<l1)goto L103;
+  
+  t1=0;
+  t2=0;
+  for(k=0;k<l1;k++){
+    t3=t1;
+    t4=t2;
+    for(i=0;i<ido;i++){
+      ch[t3]=cc[t4];
+      t3++;
+      t4++;
+    }
+    t1+=ido;
+    t2+=t10;
+  }
+  goto L106;
+
+ L103:
+  t1=0;
+  for(i=0;i<ido;i++){
+    t2=t1;
+    t3=t1;
+    for(k=0;k<l1;k++){
+      ch[t2]=cc[t3];
+      t2+=ido;
+      t3+=t10;
+    }
+    t1++;
+  }
+
+ L106:
+  t1=0;
+  t2=ipp2*t0;
+  t7=(t5=ido<<1);
+  for(j=1;j<ipph;j++){
+    t1+=t0;
+    t2-=t0;
+    t3=t1;
+    t4=t2;
+    t6=t5;
+    for(k=0;k<l1;k++){
+      ch[t3]=cc[t6-1]+cc[t6-1];
+      ch[t4]=cc[t6]+cc[t6];
+      t3+=ido;
+      t4+=ido;
+      t6+=t10;
+    }
+    t5+=t7;
+  }
+
+  if (ido == 1)goto L116;
+  if(nbd<l1)goto L112;
+
+  t1=0;
+  t2=ipp2*t0;
+  t7=0;
+  for(j=1;j<ipph;j++){
+    t1+=t0;
+    t2-=t0;
+    t3=t1;
+    t4=t2;
+
+    t7+=(ido<<1);
+    t8=t7;
+    for(k=0;k<l1;k++){
+      t5=t3;
+      t6=t4;
+      t9=t8;
+      t11=t8;
+      for(i=2;i<ido;i+=2){
+        t5+=2;
+        t6+=2;
+        t9+=2;
+        t11-=2;
+        ch[t5-1]=cc[t9-1]+cc[t11-1];
+        ch[t6-1]=cc[t9-1]-cc[t11-1];
+        ch[t5]=cc[t9]-cc[t11];
+        ch[t6]=cc[t9]+cc[t11];
+      }
+      t3+=ido;
+      t4+=ido;
+      t8+=t10;
+    }
+  }
+  goto L116;
+
+ L112:
+  t1=0;
+  t2=ipp2*t0;
+  t7=0;
+  for(j=1;j<ipph;j++){
+    t1+=t0;
+    t2-=t0;
+    t3=t1;
+    t4=t2;
+    t7+=(ido<<1);
+    t8=t7;
+    t9=t7;
+    for(i=2;i<ido;i+=2){
+      t3+=2;
+      t4+=2;
+      t8+=2;
+      t9-=2;
+      t5=t3;
+      t6=t4;
+      t11=t8;
+      t12=t9;
+      for(k=0;k<l1;k++){
+        ch[t5-1]=cc[t11-1]+cc[t12-1];
+        ch[t6-1]=cc[t11-1]-cc[t12-1];
+        ch[t5]=cc[t11]-cc[t12];
+        ch[t6]=cc[t11]+cc[t12];
+        t5+=ido;
+        t6+=ido;
+        t11+=t10;
+        t12+=t10;
+      }
+    }
+  }
+
+L116:
+  ar1=1.f;
+  ai1=0.f;
+  t1=0;
+  t9=(t2=ipp2*idl1);
+  t3=(ip-1)*idl1;
+  for(l=1;l<ipph;l++){
+    t1+=idl1;
+    t2-=idl1;
+
+    ar1h=dcp*ar1-dsp*ai1;
+    ai1=dcp*ai1+dsp*ar1;
+    ar1=ar1h;
+    t4=t1;
+    t5=t2;
+    t6=0;
+    t7=idl1;
+    t8=t3;
+    for(ik=0;ik<idl1;ik++){
+      c2[t4++]=ch2[t6++]+ar1*ch2[t7++];
+      c2[t5++]=ai1*ch2[t8++];
+    }
+    dc2=ar1;
+    ds2=ai1;
+    ar2=ar1;
+    ai2=ai1;
+
+    t6=idl1;
+    t7=t9-idl1;
+    for(j=2;j<ipph;j++){
+      t6+=idl1;
+      t7-=idl1;
+      ar2h=dc2*ar2-ds2*ai2;
+      ai2=dc2*ai2+ds2*ar2;
+      ar2=ar2h;
+      t4=t1;
+      t5=t2;
+      t11=t6;
+      t12=t7;
+      for(ik=0;ik<idl1;ik++){
+        c2[t4++]+=ar2*ch2[t11++];
+        c2[t5++]+=ai2*ch2[t12++];
+      }
+    }
+  }
+
+  t1=0;
+  for(j=1;j<ipph;j++){
+    t1+=idl1;
+    t2=t1;
+    for(ik=0;ik<idl1;ik++)ch2[ik]+=ch2[t2++];
+  }
+
+  t1=0;
+  t2=ipp2*t0;
+  for(j=1;j<ipph;j++){
+    t1+=t0;
+    t2-=t0;
+    t3=t1;
+    t4=t2;
+    for(k=0;k<l1;k++){
+      ch[t3]=c1[t3]-c1[t4];
+      ch[t4]=c1[t3]+c1[t4];
+      t3+=ido;
+      t4+=ido;
+    }
+  }
+
+  if(ido==1)goto L132;
+  if(nbd<l1)goto L128;
+
+  t1=0;
+  t2=ipp2*t0;
+  for(j=1;j<ipph;j++){
+    t1+=t0;
+    t2-=t0;
+    t3=t1;
+    t4=t2;
+    for(k=0;k<l1;k++){
+      t5=t3;
+      t6=t4;
+      for(i=2;i<ido;i+=2){
+        t5+=2;
+        t6+=2;
+        ch[t5-1]=c1[t5-1]-c1[t6];
+        ch[t6-1]=c1[t5-1]+c1[t6];
+        ch[t5]=c1[t5]+c1[t6-1];
+        ch[t6]=c1[t5]-c1[t6-1];
+      }
+      t3+=ido;
+      t4+=ido;
+    }
+  }
+  goto L132;
+
+ L128:
+  t1=0;
+  t2=ipp2*t0;
+  for(j=1;j<ipph;j++){
+    t1+=t0;
+    t2-=t0;
+    t3=t1;
+    t4=t2;
+    for(i=2;i<ido;i+=2){
+      t3+=2;
+      t4+=2;
+      t5=t3;
+      t6=t4;
+      for(k=0;k<l1;k++){
+        ch[t5-1]=c1[t5-1]-c1[t6];
+        ch[t6-1]=c1[t5-1]+c1[t6];
+        ch[t5]=c1[t5]+c1[t6-1];
+        ch[t6]=c1[t5]-c1[t6-1];
+        t5+=ido;
+        t6+=ido;
+      }
+    }
+  }
+
+L132:
+  if(ido==1)return;
+
+  for(ik=0;ik<idl1;ik++)c2[ik]=ch2[ik];
+
+  t1=0;
+  for(j=1;j<ip;j++){
+    t2=(t1+=t0);
+    for(k=0;k<l1;k++){
+      c1[t2]=ch[t2];
+      t2+=ido;
+    }
+  }
+
+  if(nbd>l1)goto L139;
+
+  is= -ido-1;
+  t1=0;
+  for(j=1;j<ip;j++){
+    is+=ido;
+    t1+=t0;
+    idij=is;
+    t2=t1;
+    for(i=2;i<ido;i+=2){
+      t2+=2;
+      idij+=2;
+      t3=t2;
+      for(k=0;k<l1;k++){
+        c1[t3-1]=wa[idij-1]*ch[t3-1]-wa[idij]*ch[t3];
+        c1[t3]=wa[idij-1]*ch[t3]+wa[idij]*ch[t3-1];
+        t3+=ido;
+      }
+    }
+  }
+  return;
+
+ L139:
+  is= -ido-1;
+  t1=0;
+  for(j=1;j<ip;j++){
+    is+=ido;
+    t1+=t0;
+    t2=t1;
+    for(k=0;k<l1;k++){
+      idij=is;
+      t3=t2;
+      for(i=2;i<ido;i+=2){
+        idij+=2;
+        t3+=2;
+        c1[t3-1]=wa[idij-1]*ch[t3-1]-wa[idij]*ch[t3];
+        c1[t3]=wa[idij-1]*ch[t3]+wa[idij]*ch[t3-1];
+      }
+      t2+=ido;
+    }
+  }
+}
+
+static void drftb1(int n, float *c, float *ch, float *wa, int *ifac){
+  int i,k1,l1,l2;
+  int na;
+  int nf,ip,iw,ix2,ix3,ido,idl1;
+
+  nf=ifac[1];
+  na=0;
+  l1=1;
+  iw=1;
+
+  for(k1=0;k1<nf;k1++){
+    ip=ifac[k1 + 2];
+    l2=ip*l1;
+    ido=n/l2;
+    idl1=ido*l1;
+    if(ip!=4)goto L103;
+    ix2=iw+ido;
+    ix3=ix2+ido;
+
+    if(na!=0)
+      dradb4(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1);
+    else
+      dradb4(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1);
+    na=1-na;
+    goto L115;
+
+  L103:
+    if(ip!=2)goto L106;
+
+    if(na!=0)
+      dradb2(ido,l1,ch,c,wa+iw-1);
+    else
+      dradb2(ido,l1,c,ch,wa+iw-1);
+    na=1-na;
+    goto L115;
+
+  L106:
+    if(ip!=3)goto L109;
+
+    ix2=iw+ido;
+    if(na!=0)
+      dradb3(ido,l1,ch,c,wa+iw-1,wa+ix2-1);
+    else
+      dradb3(ido,l1,c,ch,wa+iw-1,wa+ix2-1);
+    na=1-na;
+    goto L115;
+
+  L109:
+/*    The radix five case can be translated later..... */
+/*    if(ip!=5)goto L112;
+
+    ix2=iw+ido;
+    ix3=ix2+ido;
+    ix4=ix3+ido;
+    if(na!=0)
+      dradb5(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1,wa+ix4-1);
+    else
+      dradb5(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1,wa+ix4-1);
+    na=1-na;
+    goto L115;
+
+  L112:*/
+    if(na!=0)
+      dradbg(ido,ip,l1,idl1,ch,ch,ch,c,c,wa+iw-1);
+    else
+      dradbg(ido,ip,l1,idl1,c,c,c,ch,ch,wa+iw-1);
+    if(ido==1)na=1-na;
+
+  L115:
+    l1=l2;
+    iw+=(ip-1)*ido;
+  }
+
+  if(na==0)return;
+
+  for(i=0;i<n;i++)c[i]=ch[i];
+}
+
+void spx_drft_forward(struct drft_lookup *l,float *data){
+  if(l->n==1)return;
+  drftf1(l->n,data,l->trigcache,l->trigcache+l->n,l->splitcache);
+}
+
+void spx_drft_backward(struct drft_lookup *l,float *data){
+  if (l->n==1)return;
+  drftb1(l->n,data,l->trigcache,l->trigcache+l->n,l->splitcache);
+}
+
+void spx_drft_init(struct drft_lookup *l,int n)
+{
+  l->n=n;
+  l->trigcache=(float*)speex_alloc(3*n*sizeof(*l->trigcache));
+  l->splitcache=(int*)speex_alloc(32*sizeof(*l->splitcache));
+  fdrffti(n, l->trigcache, l->splitcache);
+}
+
+void spx_drft_clear(struct drft_lookup *l)
+{
+  if(l)
+  {
+    if(l->trigcache)
+      speex_free(l->trigcache);
+    if(l->splitcache)
+      speex_free(l->splitcache);
+  }
+}
diff --git a/jni/pjproject-android/.svn/pristine/36/36b49b116c4205e2d08e4b56502528905c4fc43d.svn-base b/jni/pjproject-android/.svn/pristine/36/36b49b116c4205e2d08e4b56502528905c4fc43d.svn-base
new file mode 100644
index 0000000..e42d20b
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/36/36b49b116c4205e2d08e4b56502528905c4fc43d.svn-base
@@ -0,0 +1,29 @@
+# $Id$
+import inc_sip as sip
+import inc_sdp as sdp
+
+# When SRTP is NOT enabled in pjsua, it should prefer to use
+# RTP/AVP media line if there are multiple m=audio lines
+sdp = \
+"""
+v=0
+o=- 0 0 IN IP4 127.0.0.1
+s=-
+c=IN IP4 127.0.0.1
+t=0 0
+m=audio 5000 RTP/SAVP 0
+a=crypto:1 aes_cm_128_hmac_sha1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ
+m=audio 4000 RTP/AVP 0
+"""
+
+pjsua_args = "--null-audio --auto-answer 200 --use-srtp 0"
+extra_headers = ""
+include = ["Content-Type: application/sdp",	# response must include SDP
+	   "m=audio 0 RTP/SAVP[\\s\\S]+m=audio [1-9]+[0-9]* RTP/AVP"
+	   ]
+exclude = ["a=crypto"]
+
+sendto_cfg = sip.SendtoCfg("Prefer RTP/SAVP", pjsua_args, sdp, 200,
+			   extra_headers=extra_headers,
+			   resp_inc=include, resp_exc=exclude) 
+
diff --git a/jni/pjproject-android/.svn/pristine/36/36d5d5f41ab85e07c7bb4b775b3238ed16386774.svn-base b/jni/pjproject-android/.svn/pristine/36/36d5d5f41ab85e07c7bb4b775b3238ed16386774.svn-base
new file mode 100644
index 0000000..b0159bf
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/36/36d5d5f41ab85e07c7bb4b775b3238ed16386774.svn-base
@@ -0,0 +1,505 @@
+/* $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
+ */
+#ifndef __PJSIP_SIMPLE_EVSUB_H__
+#define __PJSIP_SIMPLE_EVSUB_H__
+
+/**
+ * @file evsub.h
+ * @brief SIP Specific Event Notification Extension (RFC 3265)
+ */
+
+#include <pjsip-simple/types.h>
+
+
+/**
+ * @defgroup PJSIP_EVENT_NOT SIP Event Notification (RFC 3265) Module
+ * @ingroup PJSIP_SIMPLE
+ * @brief Core Event Subscription framework, used by presence, call transfer, etc.
+ * @{
+ *
+ * This module provides the implementation of SIP Extension for SIP Specific
+ * Event Notification (RFC 3265). It extends PJSIP by supporting SUBSCRIBE and
+ * NOTIFY methods.
+ *
+ * This module itself is extensible; new event packages can be registered to
+ * this module to handle specific extensions (such as presence).
+ */
+
+PJ_BEGIN_DECL
+
+
+/**
+ * Opaque type for event subscription session.
+ */
+typedef struct pjsip_evsub pjsip_evsub;
+
+
+/**
+ * This enumeration describes basic subscription state as described in the 
+ * RFC 3265. The standard specifies that extensions may define additional 
+ * states. In the case where the state is not known, the subscription state
+ * will be set to PJSIP_EVSUB_STATE_UNKNOWN, and the token will be kept
+ * in state_str member of the susbcription structure.
+ */
+enum pjsip_evsub_state
+{
+    PJSIP_EVSUB_STATE_NULL,	 /**< State is NULL.			    */
+    PJSIP_EVSUB_STATE_SENT,	 /**< Client has sent SUBSCRIBE request.    */
+    PJSIP_EVSUB_STATE_ACCEPTED,	 /**< 2xx response to SUBSCRIBE has been 
+				      sent/received.			    */
+    PJSIP_EVSUB_STATE_PENDING,	 /**< Subscription is pending.		    */
+    PJSIP_EVSUB_STATE_ACTIVE,	 /**< Subscription is active.		    */
+    PJSIP_EVSUB_STATE_TERMINATED,/**< Subscription is terminated.	    */
+    PJSIP_EVSUB_STATE_UNKNOWN,	 /**< Subscription state can not be determined.
+				      Application can query the state by 
+				      calling #pjsip_evsub_get_state_name().*/
+};
+
+/**
+ * @see pjsip_evsub_state
+ */
+typedef enum pjsip_evsub_state pjsip_evsub_state;
+
+
+/**
+ * Some options for the event subscription.
+ */
+enum
+{
+    /** 
+     * If this flag is set, then outgoing request to create subscription
+     * will not have id in the Event header (e.g. in REFER request). But if 
+     * there is an id in the incoming NOTIFY, that id will be used.
+     */
+    PJSIP_EVSUB_NO_EVENT_ID  = 1,
+};
+
+
+/**
+ * This structure describes callback that is registered by application or
+ * package to receive notifications about subscription events.
+ */
+struct pjsip_evsub_user
+{
+    /**
+     * This callback is called when subscription state has changed.
+     * Application MUST be prepared to receive NULL event and events with
+     * type other than PJSIP_EVENT_TSX_STATE
+     *
+     * This callback is OPTIONAL.
+     *
+     * @param sub	The subscription instance.
+     * @param event	The event that has caused the state to change,
+     *			which may be NULL or may have type other than
+     *			PJSIP_EVENT_TSX_STATE.
+     */
+    void (*on_evsub_state)( pjsip_evsub *sub, pjsip_event *event);
+
+    /**
+     * This callback is called when transaction state has changed.
+     *
+     * @param sub	The subscription instance.
+     * @param tsx	Transaction.
+     * @param event	The event.
+     */
+    void (*on_tsx_state)(pjsip_evsub *sub, pjsip_transaction *tsx,
+			 pjsip_event *event);
+
+    /**
+     * This callback is called when incoming SUBSCRIBE (or any method that
+     * establishes the subscription in the first place) is received. It 
+     * allows application to specify what response should be sent to 
+     * remote, along with additional headers and message body to be put 
+     * in the response.
+     *
+     * This callback is OPTIONAL.
+     *
+     * However, implementation MUST send NOTIFY request upon receiving this
+     * callback. The suggested behavior is to call 
+     * #pjsip_evsub_current_notify(), since this function takes care
+     * about unsubscription request and calculates the appropriate expiration
+     * interval.
+     */
+    void (*on_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);
+
+    /**
+     * This callback is called when client/subscriber received incoming
+     * NOTIFY request. It allows the application to specify what response
+     * should be sent to remote, along with additional headers and message
+     * body to be put in the response.
+     *
+     * This callback is OPTIONAL. When it is not implemented, the default
+     * behavior is to respond incoming NOTIFY request with 200 (OK).
+     *
+     * @param sub	The subscription instance.
+     * @param rdata	The received NOTIFY request.
+     * @param p_st_code	Application MUST set the value of this argument with
+     *			final status code (200-699) upon returning from the
+     *			callback.
+     * @param p_st_text	Custom status text, if any.
+     * @param res_hdr	Upon return, application can put additional headers 
+     *			to be sent in the response in this list.
+     * @param p_body	Application MAY specify message body to be sent in
+     *			the response.
+     */
+    void (*on_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);
+
+    /**
+     * This callback is called when it is time for the client to refresh
+     * the subscription.
+     *
+     * This callback is OPTIONAL when PJSIP package such as presence or 
+     * refer is used; the event package will refresh subscription by sending
+     * SUBSCRIBE with the interval set to current/last interval.
+     *
+     * @param sub	The subscription instance.
+     */
+    void (*on_client_refresh)(pjsip_evsub *sub);
+
+    /**
+     * This callback is called when server doesn't receive subscription 
+     * refresh after the specified subscription interval.
+     *
+     * This callback is OPTIONAL when PJSIP package such as presence or 
+     * refer is used; the event package send NOTIFY to terminate the 
+     * subscription.
+     */
+    void (*on_server_timeout)(pjsip_evsub *sub);
+
+};
+
+
+/**
+ * @see pjsip_evsub_user
+ */
+typedef struct pjsip_evsub_user pjsip_evsub_user;
+
+
+/**
+ * SUBSCRIBE method constant. @see pjsip_get_subscribe_method()
+ */
+PJ_DECL_DATA(const pjsip_method) pjsip_subscribe_method;
+
+/**
+ * NOTIFY method constant. @see pjsip_get_notify_method()
+ */
+PJ_DECL_DATA(const pjsip_method) pjsip_notify_method;
+
+/**
+ * SUBSCRIBE method constant.
+ */
+PJ_DECL(const pjsip_method*) pjsip_get_subscribe_method(void);
+
+/**
+ * NOTIFY method constant.
+ */
+PJ_DECL(const pjsip_method*) pjsip_get_notify_method(void);
+
+
+/**
+ * Initialize the event subscription module and register the module to the 
+ * specified endpoint.
+ *
+ * @param endpt		The endpoint instance.
+ *
+ * @return		PJ_SUCCESS if module can be created and registered
+ *			successfully.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_init_module(pjsip_endpoint *endpt);
+
+
+/**
+ * Get the event subscription module instance that was previously created 
+ * and registered to endpoint.
+ *
+ * @return		The event subscription module instance.
+ */
+PJ_DECL(pjsip_module*) pjsip_evsub_instance(void);
+
+
+/**
+ * Register event package to the event subscription framework.
+ *
+ * @param pkg_mod	The module that implements the event package being
+ *			registered.
+ * @param event_name	Event package identification.
+ * @param expires	Default subscription expiration time, in seconds.
+ * @param accept_cnt	Number of strings in Accept array.
+ * @param accept	Array of Accept value.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_register_pkg( pjsip_module *pkg_mod,
+					       const pj_str_t *event_name,
+					       unsigned expires,
+					       unsigned accept_cnt,
+					       const pj_str_t accept[]);
+
+/**
+ * Get the Allow-Events header. This header is built based on the packages
+ * that are registered to the evsub module.
+ *
+ * @param m		Pointer to event subscription module instance, or
+ *			NULL to use default instance (equal to 
+ *			#pjsip_evsub_instance()).
+ *
+ * @return		The Allow-Events header.
+ */
+PJ_DECL(const pjsip_hdr*) pjsip_evsub_get_allow_events_hdr(pjsip_module *m);
+
+
+/**
+ * Create client subscription session.
+ *
+ * @param dlg		The underlying dialog to use.
+ * @param user_cb	Callback to receive event subscription notifications.
+ * @param event		Event name.
+ * @param option	Bitmask of options.
+ * @param p_evsub	Pointer to receive event subscription instance.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_create_uac( pjsip_dialog *dlg,
+					     const pjsip_evsub_user *user_cb,
+					     const pj_str_t *event,
+					     unsigned option,
+					     pjsip_evsub **p_evsub);
+
+/**
+ * Create server subscription session.
+ *
+ * @param dlg		The underlying dialog to use.
+ * @param user_cb	Callback to receive event subscription notifications.
+ * @param rdata		The incoming request that creates the event 
+ *			subscription, such as SUBSCRIBE or REFER.
+ * @param option	Bitmask of options.
+ * @param p_evsub	Pointer to receive event subscription instance.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_create_uas( pjsip_dialog *dlg,
+					     const pjsip_evsub_user *user_cb,
+					     pjsip_rx_data *rdata,
+					     unsigned option,
+					     pjsip_evsub **p_evsub);
+
+/**
+ * Forcefully destroy the subscription session. This function should only
+ * be called on special condition, such as when the subscription 
+ * initialization has failed. For other conditions, application MUST terminate
+ * the subscription by sending the appropriate un(SUBSCRIBE) or NOTIFY.
+ *
+ * @param sub		The event subscription.
+ * @param notify	Specify whether the state notification callback
+ *			should be called.
+ *
+ * @return		PJ_SUCCESS if subscription session has been destroyed.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_terminate( pjsip_evsub *sub,
+					    pj_bool_t notify );
+
+
+/**
+ * Get subscription state.
+ *
+ * @param sub		Event subscription instance.
+ *
+ * @return		Subscription state.
+ */
+PJ_DECL(pjsip_evsub_state) pjsip_evsub_get_state(pjsip_evsub *sub);
+
+
+/**
+ * Get the string representation of the subscription state.
+ *
+ * @param sub		Event subscription instance.
+ *
+ * @return		NULL terminated string.
+ */
+PJ_DECL(const char*) pjsip_evsub_get_state_name(pjsip_evsub *sub);
+
+
+/**
+ * Get subscription termination reason, if any. If remote did not
+ * send termination reason, this function will return empty string.
+ *
+ * @param sub		Event subscription instance.
+ *
+ * @return		NULL terminated string.
+ */
+PJ_DECL(const pj_str_t*) pjsip_evsub_get_termination_reason(pjsip_evsub *sub);
+
+
+/**
+ * Call this function to create request to initiate subscription, to 
+ * refresh subcription, or to request subscription termination.
+ *
+ * @param sub		Client subscription instance.
+ * @param method	The method that establishes the subscription, such as
+ *			SUBSCRIBE or REFER. If this argument is NULL, then
+ *			SUBSCRIBE will be used.
+ * @param expires	Subscription expiration. If the value is set to zero,
+ *			this will request unsubscription. If the value is
+ *			negative, default expiration as defined by the package
+ *			will be used.
+ * @param p_tdata	Pointer to receive the request.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_initiate( pjsip_evsub *sub,
+					   const pjsip_method *method,
+					   pj_int32_t expires,
+					   pjsip_tx_data **p_tdata);
+
+
+/**
+ * Add a list of headers to the subscription instance. The list of headers
+ * will be added to outgoing presence subscription requests.
+ *
+ * @param sub		Subscription instance.
+ * @param hdr_list	List of headers to be added.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_add_header( pjsip_evsub *sub,
+					     const pjsip_hdr *hdr_list );
+
+
+/**
+ * Accept the incoming subscription request by sending 2xx response to
+ * incoming SUBSCRIBE request.
+ *
+ * @param sub		Server subscription instance.
+ * @param rdata		The incoming subscription request message.
+ * @param st_code	Status code, which MUST be final response.
+ * @param hdr_list	Optional list of headers to be added in the response.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_accept( pjsip_evsub *sub,
+					 pjsip_rx_data *rdata,
+				         int st_code,
+					 const pjsip_hdr *hdr_list );
+
+
+/**
+ * For notifier, create NOTIFY request to subscriber, and set the state 
+ * of the subscription.
+ *
+ * @param sub		The server subscription (notifier) instance.
+ * @param state		New state to set.
+ * @param state_str	The state string name, if state contains value other
+ *			than active, pending, or terminated. Otherwise this
+ *			argument is ignored.
+ * @param reason	Specify reason if new state is terminated, otherwise
+ *			put NULL.
+ * @param p_tdata	Pointer to receive request message.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_notify( pjsip_evsub *sub,
+					 pjsip_evsub_state state,
+					 const pj_str_t *state_str,
+					 const pj_str_t *reason,
+					 pjsip_tx_data **p_tdata);
+
+
+/**
+ * For notifier, create a NOTIFY request that reflects current subscription
+ * status.
+ *
+ * @param sub		The server subscription instance.
+ * @param p_tdata	Pointer to receive the request messge.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_current_notify( pjsip_evsub *sub,
+						 pjsip_tx_data **p_tdata );
+
+
+
+/**
+ * Send request message that was previously created with initiate(), notify(),
+ * or current_notify(). Application may also send request created with other
+ * functions, e.g. authentication. But the request MUST be either request
+ * that creates/refresh subscription or NOTIFY request.
+ *
+ * @param sub		The event subscription object.
+ * @param tdata		Request message to be send.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_send_request( pjsip_evsub *sub,
+					       pjsip_tx_data *tdata);
+
+
+
+/**
+ * Get the event subscription instance associated with the specified 
+ * transaction.
+ *
+ * @param tsx		The transaction.
+ *
+ * @return		The event subscription instance registered in the
+ *			transaction, if any.
+ */
+PJ_DECL(pjsip_evsub*) pjsip_tsx_get_evsub(pjsip_transaction *tsx);
+
+
+/**
+ * Set event subscription's module data.
+ *
+ * @param sub		The event subscription.
+ * @param mod_id	The module id.
+ * @param data		Arbitrary data.
+ */
+PJ_DECL(void) pjsip_evsub_set_mod_data( pjsip_evsub *sub, unsigned mod_id,
+				        void *data );
+
+
+/**
+ * Get event subscription's module data.
+ *
+ * @param sub		The event subscription.
+ * @param mod_id	The module id.
+ *
+ * @return		Data previously set at the specified id.
+ */
+PJ_DECL(void*) pjsip_evsub_get_mod_data( pjsip_evsub *sub, unsigned mod_id );
+
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif	/* __PJSIP_SIMPLE_EVSUB_H__ */