Index: cdr/cdr_sqlite.c
diff -Nau cdr/cdr_sqlite.c.orig cdr/cdr_sqlite.c
--- cdr/cdr_sqlite.c.orig	2007-06-14 23:50:40.000000000 +0200
+++ cdr/cdr_sqlite.c	2009-04-24 00:30:33.000000000 +0200
@@ -58,7 +58,7 @@
 #define DATE_FORMAT "%Y-%m-%d %T"
 
 static char *name = "sqlite";
-static sqlite* db = NULL;
+static sqlite3 *db = NULL;
 
 AST_MUTEX_DEFINE_STATIC(sqlite_lock);
 
@@ -92,10 +92,10 @@
 static int sqlite_log(struct ast_cdr *cdr)
 {
 	int res = 0;
-	char *zErr = 0;
 	struct tm tm;
 	time_t t;
 	char startstr[80], answerstr[80], endstr[80];
+    char *cdrsql = 0;
 	int count;
 
 	ast_mutex_lock(&sqlite_lock);
@@ -113,7 +113,7 @@
 	strftime(endstr, sizeof(endstr), DATE_FORMAT, &tm);
 
 	for(count=0; count<5; count++) {
-		res = sqlite_exec_printf(db,
+		cdrsql = sqlite3_mprintf(
 			"INSERT INTO cdr ("
 				"clid,src,dst,dcontext,"
 				"channel,dstchannel,lastapp,lastdata, "
@@ -138,8 +138,7 @@
 #				if LOG_USERFIELD
 				",'%q'"
 #				endif
-			")", NULL, NULL, &zErr,
-				cdr->clid, cdr->src, cdr->dst, cdr->dcontext,
+			")", cdr->clid, cdr->src, cdr->dst, cdr->dcontext,
 				cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata,
 				startstr, answerstr, endstr,
 				cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags,
@@ -151,16 +150,13 @@
 				,cdr->userfield
 #				endif
 			);
+			res = sqlite3_exec(db, cdrsql, 0, 0, 0);
+			sqlite3_free(cdrsql);
 		if (res != SQLITE_BUSY && res != SQLITE_LOCKED)
 			break;
 		usleep(200);
 	}
 	
-	if (zErr) {
-		ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
-		free(zErr);
-	}
-
 	ast_mutex_unlock(&sqlite_lock);
 	return res;
 }
@@ -168,7 +164,7 @@
 static int unload_module(void)
 {
 	if (db)
-		sqlite_close(db);
+		sqlite3_close(db);
 	ast_cdr_unregister(name);
 	return 0;
 }
@@ -181,17 +177,16 @@
 
 	/* is the database there? */
 	snprintf(fn, sizeof(fn), "%s/cdr.db", ast_config_AST_LOG_DIR);
-	db = sqlite_open(fn, 0660, &zErr);
+	sqlite3_open(fn, &db);
 	if (!db) {
-		ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
-		free(zErr);
+		ast_log(LOG_ERROR, "cdr_sqlite: %s\n", sqlite3_errmsg(db));
 		return -1;
 	}
 
 	/* is the table there? */
-	res = sqlite_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL);
+	res = sqlite3_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL);
 	if (res) {
-		res = sqlite_exec(db, sql_create_table, NULL, NULL, &zErr);
+		res = sqlite3_exec(db, sql_create_table, NULL, NULL, &zErr);
 		if (res) {
 			ast_log(LOG_ERROR, "cdr_sqlite: Unable to create table 'cdr': %s\n", zErr);
 			free(zErr);
@@ -210,7 +205,7 @@
 
 err:
 	if (db)
-		sqlite_close(db);
+		sqlite3_close(db);
 	return -1;
 }
 
Index: channels/chan_sip.c
diff -Nau channels/chan_sip.c.orig channels/chan_sip.c
--- channels/chan_sip.c.orig	2009-04-02 19:20:22.000000000 +0200
+++ channels/chan_sip.c	2009-04-24 00:30:33.000000000 +0200
@@ -7469,7 +7469,7 @@
 
 	ast_copy_string(from, get_header(&p->initreq, "From"), sizeof(from));
 	c = get_in_brackets(from);
-	if (strncasecmp(c, "sip:", 4)) {
+	if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) {
 		ast_log(LOG_WARNING, "Huh?  Not a SIP header (%s)?\n", c);
 		return -1;
 	}
@@ -7477,7 +7477,7 @@
 
 	ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to));
 	c = get_in_brackets(to);
-	if (strncasecmp(c, "sip:", 4)) {
+	if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) {
 		ast_log(LOG_WARNING, "Huh?  Not a SIP header (%s)?\n", c);
 		return -1;
 	}
@@ -8004,7 +8004,10 @@
 	of = get_in_brackets(from);
 	ast_string_field_set(p, from, of);
 	if (strncasecmp(of, "sip:", 4))
-		ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
+		if (strncasecmp(of, "sips:", 5))
+			ast_log(LOG_NOTICE, "From address missing 'sip:' or 'sips:', using it anyway\n");
+		else
+			of += 5;
 	else
 		of += 4;
 	/* Get just the username part */
@@ -8280,7 +8283,10 @@
 
 	/* Make sure it's a SIP URL */
 	if (strncasecmp(contact, "sip:", 4)) {
-		ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", contact);
+		if (strncasecmp(contact, "sips:", 5))
+			ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip: or sips:) trying to use anyway\n", contact);
+		else
+			contact += 5;
 	} else
 		contact += 4;
 
@@ -8409,7 +8415,10 @@
 
 	/* Make sure it's a SIP URL */
 	if (strncasecmp(curi, "sip:", 4)) {
-		ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", curi);
+		if (strncasecmp(curi, "sips:", 5))
+			ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip: or sips:) trying to use anyway\n", curi);
+		else
+			curi += 5;
 	} else
 		curi += 4;
 	/* Ditch q */
@@ -9000,9 +9009,12 @@
 
 	if (!strncasecmp(c, "sip:", 4)) {
 		name = c + 4;
+	}
+	else if (!strncasecmp(c, "sips:", 5)) {
+		name = c + 5;
 	} else {
 		name = c;
-		ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr));
+		ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip: or sips:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr));
 	}
 
 	/* Strip off the domain name */
@@ -9162,10 +9174,15 @@
 		return 0;
 	c = get_in_brackets(tmp);
 	if (strncasecmp(c, "sip:", 4)) {
-		ast_log(LOG_WARNING, "Huh?  Not an RDNIS SIP header (%s)?\n", c);
-		return -1;
+		if (strncasecmp(c, "sips:", 5)) {
+			ast_log(LOG_WARNING, "Huh?  Not an RDNIS SIP header (%s)?\n", c);
+			return -1;
+		}
+		else
+			c += 5;
 	}
-	c += 4;
+	else
+		c += 4;
 	a = c;
 	strsep(&a, "@;");	/* trim anything after @ or ; */
 	if (sip_debug_test_pvt(p))
@@ -9200,10 +9217,15 @@
 	uri = get_in_brackets(tmp);
 
 	if (strncasecmp(uri, "sip:", 4)) {
-		ast_log(LOG_WARNING, "Huh?  Not a SIP header (%s)?\n", uri);
-		return -1;
+		if (strncasecmp(uri, "sips:", 5)) {
+			ast_log(LOG_WARNING, "Huh?  Not a SIP header (%s)?\n", uri);
+			return -1;
+		}
+		else
+			uri += 5;
 	}
-	uri += 4;
+	else
+		uri += 4;
 
 	/* Now find the From: caller ID and name */
 	ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf));
@@ -9217,10 +9239,15 @@
 	
 	if (!ast_strlen_zero(from)) {
 		if (strncasecmp(from, "sip:", 4)) {
-			ast_log(LOG_WARNING, "Huh?  Not a SIP header (%s)?\n", from);
-			return -1;
+			if (strncasecmp(from, "sips:", 5)) {
+				ast_log(LOG_WARNING, "Huh?  Not a SIP header (%s)?\n", from);
+				return -1;
+			}
+			else
+				from += 5;
 		}
-		from += 4;
+		else
+			from += 4;
 		if ((a = strchr(from, '@')))
 			*a++ = '\0';
 		else
@@ -9397,10 +9424,15 @@
 		ast_uri_decode(refer_to);
 
 	if (strncasecmp(refer_to, "sip:", 4)) {
-		ast_log(LOG_WARNING, "Can't transfer to non-sip: URI.  (Refer-to: %s)?\n", refer_to);
-		return -3;
+		if (strncasecmp(refer_to, "sips:", 5)) {
+			ast_log(LOG_WARNING, "Can't transfer to non-sip: URI.  (Refer-to: %s)?\n", refer_to);
+			return -3;
+		}
+		else
+			refer_to += 5;			/* Skip sips: */
 	}
-	refer_to += 4;			/* Skip sip: */
+	else
+		refer_to += 4;			/* Skip sip: */
 
 	/* Get referred by header if it exists */
 	p_referred_by = get_header(req, "Referred-By");
@@ -9417,9 +9449,13 @@
 		}
 
 		referred_by_uri = get_in_brackets(h_referred_by);
-		if(strncasecmp(referred_by_uri, "sip:", 4)) {
-			ast_log(LOG_WARNING, "Huh?  Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri);
-			referred_by_uri = (char *) NULL;
+		if (strncasecmp(referred_by_uri, "sip:", 4)) {
+			if (strncasecmp(referred_by_uri, "sips:", 5)) {
+				ast_log(LOG_WARNING, "Huh?  Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri);
+				referred_by_uri = (char *) NULL;
+			}
+			else
+				referred_by_uri += 5;		/* Skip sips: */
 		} else {
 			referred_by_uri += 4;		/* Skip sip: */
 		}
@@ -9547,10 +9583,15 @@
 		ast_uri_decode(c);
 	
 	if (strncasecmp(c, "sip:", 4)) {
-		ast_log(LOG_WARNING, "Huh?  Not a SIP header in Also: transfer (%s)?\n", c);
-		return -1;
+		if (strncasecmp(c, "sips:", 5)) {
+			ast_log(LOG_WARNING, "Huh?  Not a SIP header in Also: transfer (%s)?\n", c);
+			return -1;
+		}
+		else
+			c += 5;
 	}
-	c += 4;
+	else
+		c += 4;
 	if ((a = strchr(c, ';'))) 	/* Remove arguments */
 		*a = '\0';
 	
@@ -9761,6 +9802,8 @@
 		t = uri2;
 		if (!strncasecmp(t, "sip:", 4))
 			t+= 4;
+		else if (!strncasecmp(t, "sips:", 5))
+			t+= 5;
 		ast_string_field_set(p, exten, t);
 		t = strchr(p->exten, '@');
 		if (t)
@@ -9771,7 +9814,10 @@
 	/* save the URI part of the From header */
 	ast_string_field_set(p, from, of);
 	if (strncasecmp(of, "sip:", 4)) {
-		ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
+		if (strncasecmp(of, "sips:", 5))
+			ast_log(LOG_NOTICE, "From address missing 'sip:' or 'sips:', using it anyway\n");
+		else
+			of += 5;
 	} else
 		of += 4;
 	/* Get just the username part */
@@ -12379,6 +12425,8 @@
 	if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
 		if (!strncasecmp(s, "sip:", 4))
 			s += 4;
+		else if (!strncasecmp(s, "sips:", 5))
+			s += 5;
 		e = strchr(s, ';');
 		if (e)
 			*e = '\0';
@@ -12404,6 +12452,8 @@
 	
 		if (!strncasecmp(s, "sip:", 4))
 			s += 4;
+		else if (!strncasecmp(s, "sips:", 5))
+			s += 5;
 		if (option_debug > 1)
 			ast_log(LOG_DEBUG, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain);
 		if (p->owner) {
Index: codecs/codec_g722.c
diff -Nau codecs/codec_g722.c.orig codecs/codec_g722.c
--- codecs/codec_g722.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ codecs/codec_g722.c	2009-04-24 00:30:33.000000000 +0200
@@ -0,0 +1,306 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2008, Digium, Inc.
+ *
+ * Matthew Fredrickson <creslin@digium.com>
+ * Russell Bryant <russell@digium.com>
+ *
+ * Special thanks to Steve Underwood for the implementation
+ * and for doing the 8khz<->g.722 direct translation code.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief codec_g722.c - translate between signed linear and ITU G.722-64kbps
+ *
+ * \author Matthew Fredrickson <creslin@digium.com>
+ * \author Russell Bryant <russell@digium.com>
+ *
+ * \arg http://soft-switch.org/downloads/non-gpl-bits.tgz
+ * \arg http://lists.digium.com/pipermail/asterisk-dev/2006-September/022866.html
+ *
+ * \ingroup codecs
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 106501 $")
+
+#include "asterisk/linkedlists.h"
+#include "asterisk/module.h"
+#include "asterisk/config.h"
+#include "asterisk/options.h"
+#include "asterisk/translate.h"
+#include "asterisk/utils.h"
+
+#define BUFFER_SAMPLES   8096	/* size for the translation buffers */
+#define BUF_SHIFT	5
+
+/* Sample frame data */
+
+#include "g722/g722.h"
+#include "slin_g722_ex.h"
+#include "g722_slin_ex.h"
+
+struct g722_encoder_pvt {
+	g722_encode_state_t g722;
+};
+
+struct g722_decoder_pvt {
+	g722_decode_state_t g722;
+};
+
+/*! \brief init a new instance of g722_encoder_pvt. */
+static int lintog722_new(struct ast_trans_pvt *pvt)
+{
+	struct g722_encoder_pvt *tmp = pvt->pvt;
+
+	g722_encode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000);
+
+	return 0;
+}
+
+static int lin16tog722_new(struct ast_trans_pvt *pvt)
+{
+	struct g722_encoder_pvt *tmp = pvt->pvt;
+
+	g722_encode_init(&tmp->g722, 64000, 0);
+
+	return 0;
+}
+
+/*! \brief init a new instance of g722_encoder_pvt. */
+static int g722tolin_new(struct ast_trans_pvt *pvt)
+{
+	struct g722_decoder_pvt *tmp = pvt->pvt;
+
+	g722_decode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000);
+
+	return 0;
+}
+
+static int g722tolin16_new(struct ast_trans_pvt *pvt)
+{
+	struct g722_decoder_pvt *tmp = pvt->pvt;
+
+	g722_decode_init(&tmp->g722, 64000, 0);
+
+	return 0;
+}
+
+static int g722tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
+{
+	struct g722_decoder_pvt *tmp = pvt->pvt;
+	int out_samples;
+	int in_samples;
+
+	/* g722_decode expects the samples to be in the invalid samples / 2 format */
+	in_samples = f->samples / 2;
+
+	out_samples = g722_decode(&tmp->g722, (int16_t *) &pvt->outbuf[pvt->samples * sizeof(int16_t)], 
+		(uint8_t *) f->data, in_samples);
+
+	pvt->samples += out_samples;
+
+	pvt->datalen += (out_samples * sizeof(int16_t));
+
+	return 0;
+}
+
+static int lintog722_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
+{
+	struct g722_encoder_pvt *tmp = pvt->pvt;
+	int outlen;
+
+	outlen = g722_encode(&tmp->g722, (uint8_t *) (&pvt->outbuf[pvt->datalen]), 
+		(int16_t *) f->data, f->samples);
+
+	pvt->samples += outlen * 2;
+
+	pvt->datalen += outlen;
+
+	return 0;
+}
+
+static struct ast_frame *g722tolin_sample(void)
+{
+	static struct ast_frame f = {
+		.frametype = AST_FRAME_VOICE,
+		.subclass = AST_FORMAT_G722,
+		.datalen = sizeof(g722_slin_ex),
+		.samples = sizeof(g722_slin_ex) * 2,
+		.src = __PRETTY_FUNCTION__,
+		.data = g722_slin_ex,
+	};
+
+	return &f;
+}
+
+static struct ast_frame *g722tolin16_sample(void)
+{
+	static struct ast_frame f = {
+		.frametype = AST_FRAME_VOICE,
+		.subclass = AST_FORMAT_G722,
+		.datalen = sizeof(slin_g722_ex),
+		.samples = sizeof(slin_g722_ex) * 2,
+		.src = __PRETTY_FUNCTION__,
+		.data = slin_g722_ex,
+	};
+
+	return &f;
+}
+
+static struct ast_frame *lintog722_sample (void)
+{
+	static struct ast_frame f = {
+		.frametype = AST_FRAME_VOICE,
+		.subclass = AST_FORMAT_SLINEAR,
+		.datalen = sizeof(slin_g722_ex),
+		.samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]),
+		.src = __PRETTY_FUNCTION__,
+		.data = slin_g722_ex,
+	};
+
+	return &f;
+}
+
+static struct ast_frame *lin16tog722_sample (void)
+{
+	static struct ast_frame f = {
+		.frametype = AST_FRAME_VOICE,
+		.subclass = AST_FORMAT_SLINEAR16,
+		.datalen = sizeof(slin_g722_ex),
+		.samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]),
+		.src = __PRETTY_FUNCTION__,
+		.data = slin_g722_ex,
+	};
+
+	return &f;
+}
+
+static struct ast_translator g722tolin = {
+	.name = "g722tolin",
+	.srcfmt = AST_FORMAT_G722,
+	.dstfmt = AST_FORMAT_SLINEAR,
+	.newpvt = g722tolin_new,	/* same for both directions */
+	.framein = g722tolin_framein,
+	.sample = g722tolin_sample,
+	.desc_size = sizeof(struct g722_decoder_pvt),
+	.buffer_samples = BUFFER_SAMPLES / sizeof(int16_t),
+	.buf_size = BUFFER_SAMPLES,
+	.plc_samples = 160,
+};
+
+static struct ast_translator lintog722 = {
+	.name = "lintog722",
+	.srcfmt = AST_FORMAT_SLINEAR,
+	.dstfmt = AST_FORMAT_G722,
+	.newpvt = lintog722_new,	/* same for both directions */
+	.framein = lintog722_framein,
+	.sample = lintog722_sample,
+	.desc_size = sizeof(struct g722_encoder_pvt),
+	.buffer_samples = BUFFER_SAMPLES * 2,
+	.buf_size = BUFFER_SAMPLES,
+};
+
+static struct ast_translator g722tolin16 = {
+	.name = "g722tolin16",
+	.srcfmt = AST_FORMAT_G722,
+	.dstfmt = AST_FORMAT_SLINEAR16,
+	.newpvt = g722tolin16_new,	/* same for both directions */
+	.framein = g722tolin_framein,
+	.sample = g722tolin16_sample,
+	.desc_size = sizeof(struct g722_decoder_pvt),
+	.buffer_samples = BUFFER_SAMPLES / sizeof(int16_t),
+	.buf_size = BUFFER_SAMPLES,
+	.plc_samples = 160,
+};
+
+static struct ast_translator lin16tog722 = {
+	.name = "lin16tog722",
+	.srcfmt = AST_FORMAT_SLINEAR16,
+	.dstfmt = AST_FORMAT_G722,
+	.newpvt = lin16tog722_new,	/* same for both directions */
+	.framein = lintog722_framein,
+	.sample = lin16tog722_sample,
+	.desc_size = sizeof(struct g722_encoder_pvt),
+	.buffer_samples = BUFFER_SAMPLES * 2,
+	.buf_size = BUFFER_SAMPLES,
+};
+
+static int parse_config(int reload)
+{
+	struct ast_variable *var;
+	struct ast_config *cfg = ast_config_load("codecs.conf");
+
+	if (cfg == NULL)
+		return 0;
+	if (cfg == CONFIG_STATUS_FILEUNCHANGED)
+		return 0;
+	for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
+		if (!strcasecmp(var->name, "genericplc")) {
+			g722tolin.useplc = ast_true(var->value) ? 1 : 0;
+			if (option_verbose > 2)
+				ast_verbose(VERBOSE_PREFIX_3 "codec_g722: %susing generic PLC\n",
+					g722tolin.useplc ? "" : "not ");
+		}
+	}
+	ast_config_destroy(cfg);
+	return 0;
+}
+
+static int reload(void)
+{
+	if (parse_config(1))
+		return AST_MODULE_LOAD_DECLINE;
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int unload_module(void)
+{
+	int res = 0;
+
+	res |= ast_unregister_translator(&g722tolin);
+	res |= ast_unregister_translator(&lintog722);
+	res |= ast_unregister_translator(&g722tolin16);
+	res |= ast_unregister_translator(&lin16tog722);
+
+	return res;
+}
+
+static int load_module(void)
+{
+	int res = 0;
+
+	if (parse_config(0))
+		return AST_MODULE_LOAD_DECLINE;
+
+	res |= ast_register_translator(&g722tolin);
+	res |= ast_register_translator(&lintog722);
+	res |= ast_register_translator(&g722tolin16);
+	res |= ast_register_translator(&lin16tog722);
+
+	if (res) {
+		unload_module();
+		return AST_MODULE_LOAD_FAILURE;
+	}	
+
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.722-64kbps G722 Transcoder",
+		.load = load_module,
+		.unload = unload_module,
+		.reload = reload,
+	       );
Index: codecs/g722/g722_decode.c
diff -Nau codecs/g722/g722_decode.c.orig codecs/g722/g722_decode.c
--- codecs/g722/g722_decode.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ codecs/g722/g722_decode.c	2009-04-24 00:30:33.000000000 +0200
@@ -0,0 +1,398 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g722_decode.c - The ITU G.722 codec, decode part.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2005 Steve Underwood
+ *
+ *  Despite my general liking of the GPL, I place my own contributions 
+ *  to this code in the public domain for the benefit of all mankind -
+ *  even the slimy ones who might try to proprietize my work and use it
+ *  to my detriment.
+ *
+ * Based in part on a single channel G.722 codec which is:
+ *
+ * Copyright (c) CMU 1993
+ * Computer Science, Speech Group
+ * Chengxiang Lu and Alex Hauptmann
+ *
+ * $Id: g722_decode.c 48661 2006-12-21 00:08:21Z mattf $
+ */
+
+/*! \file */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <memory.h>
+#include <stdlib.h>
+#if 0
+#include <tgmath.h>
+#endif
+
+#include "g722.h"
+
+#if !defined(FALSE)
+#define FALSE 0
+#endif
+#if !defined(TRUE)
+#define TRUE (!FALSE)
+#endif
+
+static __inline__ int16_t saturate(int32_t amp)
+{
+    int16_t amp16;
+
+    /* Hopefully this is optimised for the common case - not clipping */
+    amp16 = (int16_t) amp;
+    if (amp == amp16)
+        return amp16;
+    if (amp > INT16_MAX)
+        return  INT16_MAX;
+    return  INT16_MIN;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void block4(g722_decode_state_t *s, int band, int d);
+
+static void block4(g722_decode_state_t *s, int band, int d)
+{
+    int wd1;
+    int wd2;
+    int wd3;
+    int i;
+
+    /* Block 4, RECONS */
+    s->band[band].d[0] = d;
+    s->band[band].r[0] = saturate(s->band[band].s + d);
+
+    /* Block 4, PARREC */
+    s->band[band].p[0] = saturate(s->band[band].sz + d);
+
+    /* Block 4, UPPOL2 */
+    for (i = 0;  i < 3;  i++)
+        s->band[band].sg[i] = s->band[band].p[i] >> 15;
+    wd1 = saturate(s->band[band].a[1] << 2);
+
+    wd2 = (s->band[band].sg[0] == s->band[band].sg[1])  ?  -wd1  :  wd1;
+    if (wd2 > 32767)
+        wd2 = 32767;
+    wd3 = (s->band[band].sg[0] == s->band[band].sg[2])  ?  128  :  -128;
+    wd3 += (wd2 >> 7);
+    wd3 += (s->band[band].a[2]*32512) >> 15;
+    if (wd3 > 12288)
+        wd3 = 12288;
+    else if (wd3 < -12288)
+        wd3 = -12288;
+    s->band[band].ap[2] = wd3;
+
+    /* Block 4, UPPOL1 */
+    s->band[band].sg[0] = s->band[band].p[0] >> 15;
+    s->band[band].sg[1] = s->band[band].p[1] >> 15;
+    wd1 = (s->band[band].sg[0] == s->band[band].sg[1])  ?  192  :  -192;
+    wd2 = (s->band[band].a[1]*32640) >> 15;
+
+    s->band[band].ap[1] = saturate(wd1 + wd2);
+    wd3 = saturate(15360 - s->band[band].ap[2]);
+    if (s->band[band].ap[1] > wd3)
+        s->band[band].ap[1] = wd3;
+    else if (s->band[band].ap[1] < -wd3)
+        s->band[band].ap[1] = -wd3;
+
+    /* Block 4, UPZERO */
+    wd1 = (d == 0)  ?  0  :  128;
+    s->band[band].sg[0] = d >> 15;
+    for (i = 1;  i < 7;  i++)
+    {
+        s->band[band].sg[i] = s->band[band].d[i] >> 15;
+        wd2 = (s->band[band].sg[i] == s->band[band].sg[0])  ?  wd1  :  -wd1;
+        wd3 = (s->band[band].b[i]*32640) >> 15;
+        s->band[band].bp[i] = saturate(wd2 + wd3);
+    }
+
+    /* Block 4, DELAYA */
+    for (i = 6;  i > 0;  i--)
+    {
+        s->band[band].d[i] = s->band[band].d[i - 1];
+        s->band[band].b[i] = s->band[band].bp[i];
+    }
+    
+    for (i = 2;  i > 0;  i--)
+    {
+        s->band[band].r[i] = s->band[band].r[i - 1];
+        s->band[band].p[i] = s->band[band].p[i - 1];
+        s->band[band].a[i] = s->band[band].ap[i];
+    }
+
+    /* Block 4, FILTEP */
+    wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]);
+    wd1 = (s->band[band].a[1]*wd1) >> 15;
+    wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]);
+    wd2 = (s->band[band].a[2]*wd2) >> 15;
+    s->band[band].sp = saturate(wd1 + wd2);
+
+    /* Block 4, FILTEZ */
+    s->band[band].sz = 0;
+    for (i = 6;  i > 0;  i--)
+    {
+        wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]);
+        s->band[band].sz += (s->band[band].b[i]*wd1) >> 15;
+    }
+    s->band[band].sz = saturate(s->band[band].sz);
+
+    /* Block 4, PREDIC */
+    s->band[band].s = saturate(s->band[band].sp + s->band[band].sz);
+}
+/*- End of function --------------------------------------------------------*/
+
+g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options)
+{
+    if (s == NULL)
+    {
+        if ((s = (g722_decode_state_t *) malloc(sizeof(*s))) == NULL)
+            return NULL;
+    }
+    memset(s, 0, sizeof(*s));
+    if (rate == 48000)
+        s->bits_per_sample = 6;
+    else if (rate == 56000)
+        s->bits_per_sample = 7;
+    else
+        s->bits_per_sample = 8;
+    if ((options & G722_SAMPLE_RATE_8000))
+        s->eight_k = TRUE;
+    if ((options & G722_PACKED)  &&  s->bits_per_sample != 8)
+        s->packed = TRUE;
+    else
+        s->packed = FALSE;
+    s->band[0].det = 32;
+    s->band[1].det = 8;
+    return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+int g722_decode_release(g722_decode_state_t *s)
+{
+    free(s);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len)
+{
+    static const int wl[8] = {-60, -30, 58, 172, 334, 538, 1198, 3042 };
+    static const int rl42[16] = {0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3,  2, 1, 0 };
+    static const int ilb[32] =
+    {
+        2048, 2093, 2139, 2186, 2233, 2282, 2332,
+        2383, 2435, 2489, 2543, 2599, 2656, 2714,
+        2774, 2834, 2896, 2960, 3025, 3091, 3158,
+        3228, 3298, 3371, 3444, 3520, 3597, 3676,
+        3756, 3838, 3922, 4008
+    };
+    static const int wh[3] = {0, -214, 798};
+    static const int rh2[4] = {2, 1, 2, 1};
+    static const int qm2[4] = {-7408, -1616,  7408,   1616};
+    static const int qm4[16] = 
+    {
+              0, -20456, -12896,  -8968, 
+          -6288,  -4240,  -2584,  -1200,
+          20456,  12896,   8968,   6288,
+           4240,   2584,   1200,      0
+    };
+    static const int qm5[32] =
+    {
+           -280,   -280, -23352, -17560,
+         -14120, -11664,  -9752,  -8184,
+          -6864,  -5712,  -4696,  -3784,
+          -2960,  -2208,  -1520,   -880,
+          23352,  17560,  14120,  11664,
+           9752,   8184,   6864,   5712,
+           4696,   3784,   2960,   2208,
+           1520,    880,    280,   -280
+    };
+    static const int qm6[64] =
+    {
+           -136,   -136,   -136,   -136,
+         -24808, -21904, -19008, -16704,
+         -14984, -13512, -12280, -11192,
+         -10232,  -9360,  -8576,  -7856,
+          -7192,  -6576,  -6000,  -5456,
+          -4944,  -4464,  -4008,  -3576,
+          -3168,  -2776,  -2400,  -2032,
+          -1688,  -1360,  -1040,   -728,
+          24808,  21904,  19008,  16704,
+          14984,  13512,  12280,  11192,
+          10232,   9360,   8576,   7856,
+           7192,   6576,   6000,   5456,
+           4944,   4464,   4008,   3576,
+           3168,   2776,   2400,   2032,
+           1688,   1360,   1040,    728,
+            432,    136,   -432,   -136
+    };
+    static const int qmf_coeffs[12] =
+    {
+           3,  -11,   12,   32, -210,  951, 3876, -805,  362, -156,   53,  -11,
+    };
+
+    int dlowt;
+    int rlow;
+    int ihigh;
+    int dhigh;
+    int rhigh;
+    int xout1;
+    int xout2;
+    int wd1;
+    int wd2;
+    int wd3;
+    int code;
+    int outlen;
+    int i;
+    int j;
+
+    outlen = 0;
+    rhigh = 0;
+    for (j = 0;  j < len;  )
+    {
+        if (s->packed)
+        {
+            /* Unpack the code bits */
+            if (s->in_bits < s->bits_per_sample)
+            {
+                s->in_buffer |= (g722_data[j++] << s->in_bits);
+                s->in_bits += 8;
+            }
+            code = s->in_buffer & ((1 << s->bits_per_sample) - 1);
+            s->in_buffer >>= s->bits_per_sample;
+            s->in_bits -= s->bits_per_sample;
+        }
+        else
+        {
+            code = g722_data[j++];
+        }
+
+        switch (s->bits_per_sample)
+        {
+        default:
+        case 8:
+            wd1 = code & 0x3F;
+            ihigh = (code >> 6) & 0x03;
+            wd2 = qm6[wd1];
+            wd1 >>= 2;
+            break;
+        case 7:
+            wd1 = code & 0x1F;
+            ihigh = (code >> 5) & 0x03;
+            wd2 = qm5[wd1];
+            wd1 >>= 1;
+            break;
+        case 6:
+            wd1 = code & 0x0F;
+            ihigh = (code >> 4) & 0x03;
+            wd2 = qm4[wd1];
+            break;
+        }
+        /* Block 5L, LOW BAND INVQBL */
+        wd2 = (s->band[0].det*wd2) >> 15;
+        /* Block 5L, RECONS */
+        rlow = s->band[0].s + wd2;
+        /* Block 6L, LIMIT */
+        if (rlow > 16383)
+            rlow = 16383;
+        else if (rlow < -16384)
+            rlow = -16384;
+
+        /* Block 2L, INVQAL */
+        wd2 = qm4[wd1];
+        dlowt = (s->band[0].det*wd2) >> 15;
+
+        /* Block 3L, LOGSCL */
+        wd2 = rl42[wd1];
+        wd1 = (s->band[0].nb*127) >> 7;
+        wd1 += wl[wd2];
+        if (wd1 < 0)
+            wd1 = 0;
+        else if (wd1 > 18432)
+            wd1 = 18432;
+        s->band[0].nb = wd1;
+            
+        /* Block 3L, SCALEL */
+        wd1 = (s->band[0].nb >> 6) & 31;
+        wd2 = 8 - (s->band[0].nb >> 11);
+        wd3 = (wd2 < 0)  ?  (ilb[wd1] << -wd2)  :  (ilb[wd1] >> wd2);
+        s->band[0].det = wd3 << 2;
+
+        block4(s, 0, dlowt);
+        
+        if (!s->eight_k)
+        {
+            /* Block 2H, INVQAH */
+            wd2 = qm2[ihigh];
+            dhigh = (s->band[1].det*wd2) >> 15;
+            /* Block 5H, RECONS */
+            rhigh = dhigh + s->band[1].s;
+            /* Block 6H, LIMIT */
+            if (rhigh > 16383)
+                rhigh = 16383;
+            else if (rhigh < -16384)
+                rhigh = -16384;
+
+            /* Block 2H, INVQAH */
+            wd2 = rh2[ihigh];
+            wd1 = (s->band[1].nb*127) >> 7;
+            wd1 += wh[wd2];
+            if (wd1 < 0)
+                wd1 = 0;
+            else if (wd1 > 22528)
+                wd1 = 22528;
+            s->band[1].nb = wd1;
+            
+            /* Block 3H, SCALEH */
+            wd1 = (s->band[1].nb >> 6) & 31;
+            wd2 = 10 - (s->band[1].nb >> 11);
+            wd3 = (wd2 < 0)  ?  (ilb[wd1] << -wd2)  :  (ilb[wd1] >> wd2);
+            s->band[1].det = wd3 << 2;
+
+            block4(s, 1, dhigh);
+        }
+
+        if (s->itu_test_mode)
+        {
+            amp[outlen++] = (int16_t) (rlow << 1);
+            amp[outlen++] = (int16_t) (rhigh << 1);
+        }
+        else
+        {
+            if (s->eight_k)
+            {
+                amp[outlen++] = (int16_t) rlow;
+            }
+            else
+            {
+                /* Apply the receive QMF */
+                for (i = 0;  i < 22;  i++)
+                    s->x[i] = s->x[i + 2];
+                s->x[22] = rlow + rhigh;
+                s->x[23] = rlow - rhigh;
+
+                xout1 = 0;
+                xout2 = 0;
+                for (i = 0;  i < 12;  i++)
+                {
+                    xout2 += s->x[2*i]*qmf_coeffs[i];
+                    xout1 += s->x[2*i + 1]*qmf_coeffs[11 - i];
+                }
+                amp[outlen++] = (int16_t) (xout1 >> 12);
+                amp[outlen++] = (int16_t) (xout2 >> 12);
+            }
+        }
+    }
+    return outlen;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/
Index: codecs/g722/g722_encode.c
diff -Nau codecs/g722/g722_encode.c.orig codecs/g722/g722_encode.c
--- codecs/g722/g722_encode.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ codecs/g722/g722_encode.c	2009-04-24 00:30:33.000000000 +0200
@@ -0,0 +1,400 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g722_encode.c - The ITU G.722 codec, encode part.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2005 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ *  Despite my general liking of the GPL, I place my own contributions 
+ *  to this code in the public domain for the benefit of all mankind -
+ *  even the slimy ones who might try to proprietize my work and use it
+ *  to my detriment.
+ *
+ * Based on a single channel 64kbps only G.722 codec which is:
+ *
+ *****    Copyright (c) CMU    1993      *****
+ * Computer Science, Speech Group
+ * Chengxiang Lu and Alex Hauptmann
+ *
+ * $Id: g722_encode.c 48661 2006-12-21 00:08:21Z mattf $
+ */
+
+/*! \file */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <memory.h>
+#include <stdlib.h>
+#if 0
+#include <tgmath.h>
+#endif
+
+#include "g722.h"
+
+#if !defined(FALSE)
+#define FALSE 0
+#endif
+#if !defined(TRUE)
+#define TRUE (!FALSE)
+#endif
+
+static __inline__ int16_t saturate(int32_t amp)
+{
+    int16_t amp16;
+
+    /* Hopefully this is optimised for the common case - not clipping */
+    amp16 = (int16_t) amp;
+    if (amp == amp16)
+        return amp16;
+    if (amp > INT16_MAX)
+        return  INT16_MAX;
+    return  INT16_MIN;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void block4(g722_encode_state_t *s, int band, int d)
+{
+    int wd1;
+    int wd2;
+    int wd3;
+    int i;
+
+    /* Block 4, RECONS */
+    s->band[band].d[0] = d;
+    s->band[band].r[0] = saturate(s->band[band].s + d);
+
+    /* Block 4, PARREC */
+    s->band[band].p[0] = saturate(s->band[band].sz + d);
+
+    /* Block 4, UPPOL2 */
+    for (i = 0;  i < 3;  i++)
+        s->band[band].sg[i] = s->band[band].p[i] >> 15;
+    wd1 = saturate(s->band[band].a[1] << 2);
+
+    wd2 = (s->band[band].sg[0] == s->band[band].sg[1])  ?  -wd1  :  wd1;
+    if (wd2 > 32767)
+        wd2 = 32767;
+    wd3 = (wd2 >> 7) + ((s->band[band].sg[0] == s->band[band].sg[2])  ?  128  :  -128);
+    wd3 += (s->band[band].a[2]*32512) >> 15;
+    if (wd3 > 12288)
+        wd3 = 12288;
+    else if (wd3 < -12288)
+        wd3 = -12288;
+    s->band[band].ap[2] = wd3;
+
+    /* Block 4, UPPOL1 */
+    s->band[band].sg[0] = s->band[band].p[0] >> 15;
+    s->band[band].sg[1] = s->band[band].p[1] >> 15;
+    wd1 = (s->band[band].sg[0] == s->band[band].sg[1])  ?  192  :  -192;
+    wd2 = (s->band[band].a[1]*32640) >> 15;
+
+    s->band[band].ap[1] = saturate(wd1 + wd2);
+    wd3 = saturate(15360 - s->band[band].ap[2]);
+    if (s->band[band].ap[1] > wd3)
+        s->band[band].ap[1] = wd3;
+    else if (s->band[band].ap[1] < -wd3)
+        s->band[band].ap[1] = -wd3;
+
+    /* Block 4, UPZERO */
+    wd1 = (d == 0)  ?  0  :  128;
+    s->band[band].sg[0] = d >> 15;
+    for (i = 1;  i < 7;  i++)
+    {
+        s->band[band].sg[i] = s->band[band].d[i] >> 15;
+        wd2 = (s->band[band].sg[i] == s->band[band].sg[0])  ?  wd1  :  -wd1;
+        wd3 = (s->band[band].b[i]*32640) >> 15;
+        s->band[band].bp[i] = saturate(wd2 + wd3);
+    }
+
+    /* Block 4, DELAYA */
+    for (i = 6;  i > 0;  i--)
+    {
+        s->band[band].d[i] = s->band[band].d[i - 1];
+        s->band[band].b[i] = s->band[band].bp[i];
+    }
+    
+    for (i = 2;  i > 0;  i--)
+    {
+        s->band[band].r[i] = s->band[band].r[i - 1];
+        s->band[band].p[i] = s->band[band].p[i - 1];
+        s->band[band].a[i] = s->band[band].ap[i];
+    }
+
+    /* Block 4, FILTEP */
+    wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]);
+    wd1 = (s->band[band].a[1]*wd1) >> 15;
+    wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]);
+    wd2 = (s->band[band].a[2]*wd2) >> 15;
+    s->band[band].sp = saturate(wd1 + wd2);
+
+    /* Block 4, FILTEZ */
+    s->band[band].sz = 0;
+    for (i = 6;  i > 0;  i--)
+    {
+        wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]);
+        s->band[band].sz += (s->band[band].b[i]*wd1) >> 15;
+    }
+    s->band[band].sz = saturate(s->band[band].sz);
+
+    /* Block 4, PREDIC */
+    s->band[band].s = saturate(s->band[band].sp + s->band[band].sz);
+}
+/*- End of function --------------------------------------------------------*/
+
+g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options)
+{
+    if (s == NULL)
+    {
+        if ((s = (g722_encode_state_t *) malloc(sizeof(*s))) == NULL)
+            return NULL;
+    }
+    memset(s, 0, sizeof(*s));
+    if (rate == 48000)
+        s->bits_per_sample = 6;
+    else if (rate == 56000)
+        s->bits_per_sample = 7;
+    else
+        s->bits_per_sample = 8;
+    if ((options & G722_SAMPLE_RATE_8000))
+        s->eight_k = TRUE;
+    if ((options & G722_PACKED)  &&  s->bits_per_sample != 8)
+        s->packed = TRUE;
+    else
+        s->packed = FALSE;
+    s->band[0].det = 32;
+    s->band[1].det = 8;
+    return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+int g722_encode_release(g722_encode_state_t *s)
+{
+    free(s);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len)
+{
+    static const int q6[32] =
+    {
+           0,   35,   72,  110,  150,  190,  233,  276,
+         323,  370,  422,  473,  530,  587,  650,  714,
+         786,  858,  940, 1023, 1121, 1219, 1339, 1458,
+        1612, 1765, 1980, 2195, 2557, 2919,    0,    0
+    };
+    static const int iln[32] =
+    {
+         0, 63, 62, 31, 30, 29, 28, 27,
+        26, 25, 24, 23, 22, 21, 20, 19,
+        18, 17, 16, 15, 14, 13, 12, 11,
+        10,  9,  8,  7,  6,  5,  4,  0
+    };
+    static const int ilp[32] =
+    {
+         0, 61, 60, 59, 58, 57, 56, 55,
+        54, 53, 52, 51, 50, 49, 48, 47,
+        46, 45, 44, 43, 42, 41, 40, 39,
+        38, 37, 36, 35, 34, 33, 32,  0
+    };
+    static const int wl[8] =
+    {
+        -60, -30, 58, 172, 334, 538, 1198, 3042
+    };
+    static const int rl42[16] =
+    {
+        0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0
+    };
+    static const int ilb[32] =
+    {
+        2048, 2093, 2139, 2186, 2233, 2282, 2332,
+        2383, 2435, 2489, 2543, 2599, 2656, 2714,
+        2774, 2834, 2896, 2960, 3025, 3091, 3158,
+        3228, 3298, 3371, 3444, 3520, 3597, 3676,
+        3756, 3838, 3922, 4008
+    };
+    static const int qm4[16] =
+    {
+             0, -20456, -12896, -8968,
+         -6288,  -4240,  -2584, -1200,
+         20456,  12896,   8968,  6288,
+          4240,   2584,   1200,     0
+    };
+    static const int qm2[4] =
+    {
+        -7408,  -1616,   7408,   1616
+    };
+    static const int qmf_coeffs[12] =
+    {
+           3,  -11,   12,   32, -210,  951, 3876, -805,  362, -156,   53,  -11,
+    };
+    static const int ihn[3] = {0, 1, 0};
+    static const int ihp[3] = {0, 3, 2};
+    static const int wh[3] = {0, -214, 798};
+    static const int rh2[4] = {2, 1, 2, 1};
+
+    int dlow;
+    int dhigh;
+    int el;
+    int wd;
+    int wd1;
+    int ril;
+    int wd2;
+    int il4;
+    int ih2;
+    int wd3;
+    int eh;
+    int mih;
+    int i;
+    int j;
+    /* Low and high band PCM from the QMF */
+    int xlow;
+    int xhigh;
+    int g722_bytes;
+    /* Even and odd tap accumulators */
+    int sumeven;
+    int sumodd;
+    int ihigh;
+    int ilow;
+    int code;
+
+    g722_bytes = 0;
+    xhigh = 0;
+    for (j = 0;  j < len;  )
+    {
+        if (s->itu_test_mode)
+        {
+            xlow =
+            xhigh = amp[j++] >> 1;
+        }
+        else
+        {
+            if (s->eight_k)
+            {
+                xlow = amp[j++];
+            }
+            else
+            {
+                /* Apply the transmit QMF */
+                /* Shuffle the buffer down */
+                for (i = 0;  i < 22;  i++)
+                    s->x[i] = s->x[i + 2];
+                s->x[22] = amp[j++];
+                s->x[23] = amp[j++];
+    
+                /* Discard every other QMF output */
+                sumeven = 0;
+                sumodd = 0;
+                for (i = 0;  i < 12;  i++)
+                {
+                    sumodd += s->x[2*i]*qmf_coeffs[i];
+                    sumeven += s->x[2*i + 1]*qmf_coeffs[11 - i];
+                }
+                xlow = (sumeven + sumodd) >> 13;
+                xhigh = (sumeven - sumodd) >> 13;
+            }
+        }
+        /* Block 1L, SUBTRA */
+        el = saturate(xlow - s->band[0].s);
+
+        /* Block 1L, QUANTL */
+        wd = (el >= 0)  ?  el  :  -(el + 1);
+
+        for (i = 1;  i < 30;  i++)
+        {
+            wd1 = (q6[i]*s->band[0].det) >> 12;
+            if (wd < wd1)
+                break;
+        }
+        ilow = (el < 0)  ?  iln[i]  :  ilp[i];
+
+        /* Block 2L, INVQAL */
+        ril = ilow >> 2;
+        wd2 = qm4[ril];
+        dlow = (s->band[0].det*wd2) >> 15;
+
+        /* Block 3L, LOGSCL */
+        il4 = rl42[ril];
+        wd = (s->band[0].nb*127) >> 7;
+        s->band[0].nb = wd + wl[il4];
+        if (s->band[0].nb < 0)
+            s->band[0].nb = 0;
+        else if (s->band[0].nb > 18432)
+            s->band[0].nb = 18432;
+
+        /* Block 3L, SCALEL */
+        wd1 = (s->band[0].nb >> 6) & 31;
+        wd2 = 8 - (s->band[0].nb >> 11);
+        wd3 = (wd2 < 0)  ?  (ilb[wd1] << -wd2)  :  (ilb[wd1] >> wd2);
+        s->band[0].det = wd3 << 2;
+
+        block4(s, 0, dlow);
+        
+        if (s->eight_k)
+        {
+            /* Just leave the high bits as zero */
+            code = (0xC0 | ilow) >> (8 - s->bits_per_sample);
+        }
+        else
+        {
+            /* Block 1H, SUBTRA */
+            eh = saturate(xhigh - s->band[1].s);
+
+            /* Block 1H, QUANTH */
+            wd = (eh >= 0)  ?  eh  :  -(eh + 1);
+            wd1 = (564*s->band[1].det) >> 12;
+            mih = (wd >= wd1)  ?  2  :  1;
+            ihigh = (eh < 0)  ?  ihn[mih]  :  ihp[mih];
+
+            /* Block 2H, INVQAH */
+            wd2 = qm2[ihigh];
+            dhigh = (s->band[1].det*wd2) >> 15;
+
+            /* Block 3H, LOGSCH */
+            ih2 = rh2[ihigh];
+            wd = (s->band[1].nb*127) >> 7;
+            s->band[1].nb = wd + wh[ih2];
+            if (s->band[1].nb < 0)
+                s->band[1].nb = 0;
+            else if (s->band[1].nb > 22528)
+                s->band[1].nb = 22528;
+
+            /* Block 3H, SCALEH */
+            wd1 = (s->band[1].nb >> 6) & 31;
+            wd2 = 10 - (s->band[1].nb >> 11);
+            wd3 = (wd2 < 0)  ?  (ilb[wd1] << -wd2)  :  (ilb[wd1] >> wd2);
+            s->band[1].det = wd3 << 2;
+
+            block4(s, 1, dhigh);
+            code = ((ihigh << 6) | ilow) >> (8 - s->bits_per_sample);
+        }
+
+        if (s->packed)
+        {
+            /* Pack the code bits */
+            s->out_buffer |= (code << s->out_bits);
+            s->out_bits += s->bits_per_sample;
+            if (s->out_bits >= 8)
+            {
+                g722_data[g722_bytes++] = (uint8_t) (s->out_buffer & 0xFF);
+                s->out_bits -= 8;
+                s->out_buffer >>= 8;
+            }
+        }
+        else
+        {
+            g722_data[g722_bytes++] = (uint8_t) code;
+        }
+    }
+    return g722_bytes;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/
Index: codecs/g722/g722.h
diff -Nau codecs/g722/g722.h.orig codecs/g722/g722.h
--- codecs/g722/g722.h.orig	1970-01-01 01:00:00.000000000 +0100
+++ codecs/g722/g722.h	2009-04-24 00:30:33.000000000 +0200
@@ -0,0 +1,148 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g722.h - The ITU G.722 codec.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2005 Steve Underwood
+ *
+ *  Despite my general liking of the GPL, I place my own contributions 
+ *  to this code in the public domain for the benefit of all mankind -
+ *  even the slimy ones who might try to proprietize my work and use it
+ *  to my detriment.
+ *
+ * Based on a single channel G.722 codec which is:
+ *
+ *****    Copyright (c) CMU    1993      *****
+ * Computer Science, Speech Group
+ * Chengxiang Lu and Alex Hauptmann
+ *
+ * $Id: g722.h 48959 2006-12-25 06:42:15Z rizzo $
+ */
+
+
+/*! \file */
+
+#if !defined(_G722_H_)
+#define _G722_H_
+
+/*! \page g722_page G.722 encoding and decoding
+\section g722_page_sec_1 What does it do?
+The G.722 module is a bit exact implementation of the ITU G.722 specification for all three
+specified bit rates - 64000bps, 56000bps and 48000bps. It passes the ITU tests.
+
+To allow fast and flexible interworking with narrow band telephony, the encoder and decoder
+support an option for the linear audio to be an 8k samples/second stream. In this mode the
+codec is considerably faster, and still fully compatible with wideband terminals using G.722.
+
+\section g722_page_sec_2 How does it work?
+???.
+*/
+
+enum
+{
+    G722_SAMPLE_RATE_8000 = 0x0001,
+    G722_PACKED = 0x0002
+};
+
+#ifndef INT16_MAX
+#define INT16_MAX       32767
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN       (-32768)
+#endif
+
+typedef struct
+{
+    /*! TRUE if the operating in the special ITU test mode, with the band split filters
+             disabled. */
+    int itu_test_mode;
+    /*! TRUE if the G.722 data is packed */
+    int packed;
+    /*! TRUE if encode from 8k samples/second */
+    int eight_k;
+    /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */
+    int bits_per_sample;
+
+    /*! Signal history for the QMF */
+    int x[24];
+
+    struct
+    {
+        int s;
+        int sp;
+        int sz;
+        int r[3];
+        int a[3];
+        int ap[3];
+        int p[3];
+        int d[7];
+        int b[7];
+        int bp[7];
+        int sg[7];
+        int nb;
+        int det;
+    } band[2];
+
+    unsigned int in_buffer;
+    int in_bits;
+    unsigned int out_buffer;
+    int out_bits;
+} g722_encode_state_t;
+
+typedef struct
+{
+    /*! TRUE if the operating in the special ITU test mode, with the band split filters
+             disabled. */
+    int itu_test_mode;
+    /*! TRUE if the G.722 data is packed */
+    int packed;
+    /*! TRUE if decode to 8k samples/second */
+    int eight_k;
+    /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */
+    int bits_per_sample;
+
+    /*! Signal history for the QMF */
+    int x[24];
+
+    struct
+    {
+        int s;
+        int sp;
+        int sz;
+        int r[3];
+        int a[3];
+        int ap[3];
+        int p[3];
+        int d[7];
+        int b[7];
+        int bp[7];
+        int sg[7];
+        int nb;
+        int det;
+    } band[2];
+    
+    unsigned int in_buffer;
+    int in_bits;
+    unsigned int out_buffer;
+    int out_bits;
+} g722_decode_state_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options);
+int g722_encode_release(g722_encode_state_t *s);
+int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len);
+
+g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options);
+int g722_decode_release(g722_decode_state_t *s);
+int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: codecs/g722/Makefile
diff -Nau codecs/g722/Makefile.orig codecs/g722/Makefile
--- codecs/g722/Makefile.orig	1970-01-01 01:00:00.000000000 +0100
+++ codecs/g722/Makefile	2009-04-24 00:30:33.000000000 +0200
@@ -0,0 +1,18 @@
+LIB=libg722.a
+CFLAGS+=-fPIC
+
+include $(ASTTOPDIR)/Makefile.rules
+
+OBJS=g722_encode.o g722_decode.o
+
+all: $(LIB)
+
+$(LIB): $(OBJS)
+	$(ECHO_PREFIX) echo "   [AR] $^ -> $@"
+	$(CMD_PREFIX) $(AR) cr $@ $^
+	$(CMD_PREFIX) $(RANLIB) $@
+
+clean:
+	rm -f $(LIB) *.o
+	rm -f .*.o.d
+	rm -f *.s *.i
Index: codecs/g722_slin_ex.h
diff -Nau codecs/g722_slin_ex.h.orig codecs/g722_slin_ex.h
--- codecs/g722_slin_ex.h.orig	1970-01-01 01:00:00.000000000 +0100
+++ codecs/g722_slin_ex.h	2009-04-24 00:30:33.000000000 +0200
@@ -0,0 +1,25 @@
+/*! \file
+ * \brief g722_slin_ex.h --
+ *
+ *	4-bit ADPCM data, 20 milliseconds worth at 8 kHz.
+ *
+ * Source: g723.example
+ *
+ * Copyright (C) 2001-2005, Digium Inc.
+ *
+ * Distributed under the terms of the GNU General Public License
+ *
+ */
+
+static unsigned char g722_slin_ex[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
Index: codecs/Makefile
diff -Nau codecs/Makefile.orig codecs/Makefile
--- codecs/Makefile.orig	2008-03-26 17:42:35.000000000 +0100
+++ codecs/Makefile	2009-04-24 00:30:33.000000000 +0200
@@ -31,6 +31,7 @@
 
 LIBILBC:=ilbc/libilbc.a
 LIBLPC10:=lpc10/liblpc10.a
+LIBG722:=g722/libg722.a
 
 all: _all
 
@@ -45,6 +46,7 @@
 	$(MAKE) -C gsm clean
 	$(MAKE) -C lpc10 clean
 	$(MAKE) -C ilbc clean
+	$(MAKE) -C g722 clean
 
 gsm/lib/libgsm.a:
 	@mkdir -p gsm/lib
@@ -59,3 +61,8 @@
 	@$(MAKE) -C ilbc all ASTCFLAGS="$(filter-out -Wmissing-prototypes -Wmissing-declarations,$(ASTCFLAGS)) $(AST_NO_STRICT_OVERFLOW)"
 
 $(if $(filter codec_ilbc,$(EMBEDDED_MODS)),modules.link,codec_ilbc.so): $(LIBILBC)
+
+$(LIBG722):
+	@$(MAKE) -C g722 all
+
+$(if $(filter codec_g722,$(EMBEDDED_MODS)),modules.link,codec_g722.so): $(LIBG722)
Index: codecs/slin_g722_ex.h
diff -Nau codecs/slin_g722_ex.h.orig codecs/slin_g722_ex.h
--- codecs/slin_g722_ex.h.orig	1970-01-01 01:00:00.000000000 +0100
+++ codecs/slin_g722_ex.h	2009-04-24 00:30:33.000000000 +0200
@@ -0,0 +1,25 @@
+/*! \file
+ * \brief slin_g722_ex.h --
+ *
+ *	Signed 16-bit audio data, 10 milliseconds worth at 8 kHz.
+ *
+ * Source: g723.example
+ *
+ * Copyright (C) 2001-2005, Digium Inc.
+ *
+ * Distributed under the terms of the GNU General Public License
+ *
+ */
+
+static signed short slin_g722_ex[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
Index: configure
diff -Nau configure.orig configure
--- configure.orig	2009-02-18 21:06:45.000000000 +0100
+++ configure	2009-04-24 00:30:33.000000000 +0200
@@ -11143,6 +11143,61 @@
 
 fi
 
+{ echo "$as_me:$LINENO: checking for tm_gmtoff in struct tm" >&5
+echo $ECHO_N "checking for tm_gmtoff in struct tm... $ECHO_C" >&6; }
+if test "${ac_cv_struct_tm_gmtoff+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <sys/types.h>
+#include <$ac_cv_struct_tm>
+int main() {
+struct tm tm; tm.tm_gmtoff;
+; return 0; }
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_struct_tm_gmtoff=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_struct_tm_gmtoff=no
+fi
+
+rm -f conftest*
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_struct_tm_gmtoff" >&5
+echo "${ECHO_T}$ac_cv_struct_tm_gmtoff" >&6; }
+if test $ac_cv_struct_tm_gmtoff = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TM_GMTOFF 1
+_ACEOF
+
+fi
+
 { echo "$as_me:$LINENO: checking for working volatile" >&5
 echo $ECHO_N "checking for working volatile... $ECHO_C" >&6; }
 if test "${ac_cv_c_volatile+set}" = set; then
Index: include/asterisk/config.h
diff -Nau include/asterisk/config.h.orig include/asterisk/config.h
--- include/asterisk/config.h.orig	2009-02-18 19:30:38.000000000 +0100
+++ include/asterisk/config.h	2009-04-24 00:30:33.000000000 +0200
@@ -33,6 +33,8 @@
 
 struct ast_category;
 
+#define	CONFIG_STATUS_FILEUNCHANGED	(void *)-1
+
 struct ast_variable {
 	char *name;
 	char *value;
Index: include/asterisk/frame.h
diff -Nau include/asterisk/frame.h.orig include/asterisk/frame.h
--- include/asterisk/frame.h.orig	2009-03-05 19:22:16.000000000 +0100
+++ include/asterisk/frame.h	2009-04-24 00:30:33.000000000 +0200
@@ -260,6 +260,8 @@
 #define AST_FORMAT_G726		(1 << 11)
 /*! G.722 */
 #define AST_FORMAT_G722		(1 << 12)
+/*! Raw 16-bit Signed Linear (16000 Hz) PCM */
+#define AST_FORMAT_SLINEAR16   (1 << 15)
 /*! Unsupported audio bits */
 #define AST_FORMAT_AUDIO_UNDEFINED	((1 << 13) | (1 << 14) | (1 << 15))
 /*! Maximum audio format */
Index: main/editline/np/vis.h
diff -Nau main/editline/np/vis.h.orig main/editline/np/vis.h
--- main/editline/np/vis.h.orig	2006-08-21 04:11:39.000000000 +0200
+++ main/editline/np/vis.h	2009-04-24 00:30:33.000000000 +0200
@@ -76,6 +76,22 @@
 
 #include <sys/cdefs.h>
 
+/* correct nonportable unsigned type usage */
+#if !defined(__FreeBSD__) && !defined(__linux__)
+#ifndef u_int64_t
+#define u_int64_t unsigned long long
+#endif
+#ifndef u_int32_t
+#define u_int32_t unsigned int
+#endif
+#ifndef u_int16_t
+#define u_int16_t unsigned short
+#endif
+#ifndef u_int6_t
+#define u_int8_t unsigned char
+#endif
+#endif
+
 __BEGIN_DECLS
 char	*vis __P((char *, int, int, int));
 char	*svis __P((char *, int, int, int, const char *));
Index: main/stdtime/localtime.c
diff -Nau main/stdtime/localtime.c.orig main/stdtime/localtime.c
--- main/stdtime/localtime.c.orig	2008-09-27 17:00:48.000000000 +0200
+++ main/stdtime/localtime.c	2009-04-24 00:30:33.000000000 +0200
@@ -1134,9 +1134,9 @@
 	*/
 	result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
 	tmp->tm_isdst = ttisp->tt_isdst;
-#ifndef SOLARIS /* Solaris doesn't have this element */
+#ifdef TM_GMTOFF
 	tmp->tm_gmtoff = ttisp->tt_gmtoff;
-#endif
+#endif /* defined TM_GMTOFF */
 #ifdef TM_ZONE
 	tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
 #endif /* defined TM_ZONE */
Index: Makefile.moddir_rules
diff -Nau Makefile.moddir_rules.orig Makefile.moddir_rules
--- Makefile.moddir_rules.orig	2008-11-26 19:36:24.000000000 +0100
+++ Makefile.moddir_rules	2009-04-24 00:30:33.000000000 +0200
@@ -69,7 +69,9 @@
 	rm -f modules.link
 
 install:: all
+ifneq ($(LOADABLE_MODS),)
 	for x in $(LOADABLE_MODS:%=%.so); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
+endif
 
 uninstall::
 
Index: res/res_features.c
diff -Nau res/res_features.c.orig res/res_features.c
--- res/res_features.c.orig	2009-03-03 19:27:09.000000000 +0100
+++ res/res_features.c	2009-04-24 00:30:33.000000000 +0200
@@ -732,6 +732,10 @@
 			snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
 		}
 
+		for( x = 0; x < strlen(touch_filename); x++) {
+			if (touch_filename[x] == '/')
+				touch_filename[x] = '-';
+		}
 		for( x = 0; x < strlen(args); x++) {
 			if (args[x] == '/')
 				args[x] = '-';
@@ -2774,6 +2778,293 @@
 	}
 }
 
+static char mandescr_bridge[] =
+"Description: Bridge together two channels already in the PBX\n"
+"Variables: ( Headers marked with * are required )\n"
+"   *Channel1: Channel to Bridge to Channel2\n"
+"   *Channel2: Channel to Bridge to Channel1\n"
+"        Tone: (Yes|No) Play courtesy tone to Channel 2\n"
+"\n";
+
+/*!
+ * \brief Actual bridge
+ * \param chan
+ * \param tmpchan
+ * 
+ * Stop hold music, lock both channels, masq channels,
+ * after bridge return channel to next priority.
+*/
+static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
+{
+	ast_moh_stop(chan);
+	ast_channel_lock(chan);
+	ast_setstate(tmpchan, chan->_state);
+	tmpchan->readformat = chan->readformat;
+	tmpchan->writeformat = chan->writeformat;
+	ast_channel_masquerade(tmpchan, chan);
+	ast_channel_lock(tmpchan);
+	ast_do_masquerade(tmpchan);
+	/* when returning from bridge, the channel will continue at the next priority */
+	ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
+	ast_channel_unlock(tmpchan);
+	ast_channel_unlock(chan);
+}
+
+/*!
+ * \brief Bridge channels together
+ * \param s
+ * \param m
+ * 
+ * Make sure valid channels were specified, 
+ * send errors if any of the channels could not be found/locked, answer channels if needed,
+ * create the placeholder channels and grab the other channels 
+ * make the channels compatible, send error if we fail doing so 
+ * setup the bridge thread object and start the bridge.
+ * 
+ * \retval 0 on success or on incorrect use.
+ * \retval 1 on failure to bridge channels.
+*/
+static int action_bridge(struct mansession *s, const struct message *m)
+{
+	const char *channela = astman_get_header(m, "Channel1");
+	const char *channelb = astman_get_header(m, "Channel2");
+	const char *playtone = astman_get_header(m, "Tone");
+	struct ast_channel *chana = NULL, *chanb = NULL;
+	struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
+	struct ast_bridge_thread_obj *tobj = NULL;
+
+	/* make sure valid channels were specified */
+	if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) {
+		chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
+		chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
+		if (chana)
+			ast_channel_unlock(chana);
+		if (chanb)
+			ast_channel_unlock(chanb);
+
+		/* send errors if any of the channels could not be found/locked */
+		if (!chana) {
+			char buf[256];
+			snprintf(buf, sizeof(buf), "Channel1 does not exist: %s", channela);
+			astman_send_error(s, m, buf);
+			return 0;
+		}
+		if (!chanb) {
+			char buf[256];
+			snprintf(buf, sizeof(buf), "Channel2 does not exist: %s", channelb);
+			astman_send_error(s, m, buf);
+			return 0;
+		}
+	} else {
+		astman_send_error(s, m, "Missing channel parameter in request");
+		return 0;
+	}
+
+	/* Answer the channels if needed */
+	if (chana->_state != AST_STATE_UP)
+		ast_answer(chana);
+	if (chanb->_state != AST_STATE_UP)
+		ast_answer(chanb);
+
+	/* create the placeholder channels and grab the other channels */
+	if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
+		NULL, NULL, 0, "Bridge/%s", chana->name))) {
+		astman_send_error(s, m, "Unable to create temporary channel!");
+		return 1;
+	}
+
+	if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
+		NULL, NULL, 0, "Bridge/%s", chanb->name))) {
+		astman_send_error(s, m, "Unable to create temporary channels!");
+		ast_channel_free(tmpchana);
+		return 1;
+	}
+
+	do_bridge_masquerade(chana, tmpchana);
+	do_bridge_masquerade(chanb, tmpchanb);
+	
+	/* make the channels compatible, send error if we fail doing so */
+	if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
+		ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
+		astman_send_error(s, m, "Could not make channels compatible for manager bridge");
+		ast_hangup(tmpchana);
+		ast_hangup(tmpchanb);
+		return 1;
+	}
+
+	/* setup the bridge thread object and start the bridge */
+	if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
+		ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
+		astman_send_error(s, m, "Unable to spawn a new bridge thread");
+		ast_hangup(tmpchana);
+		ast_hangup(tmpchanb);
+		return 1;
+	}
+
+	tobj->chan = tmpchana;
+	tobj->peer = tmpchanb;
+	
+	if (ast_true(playtone)) {
+		if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
+			if (ast_waitstream(tmpchanb, "") < 0)
+				ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
+		}
+	}
+
+	ast_bridge_call_thread_launch(tobj);
+
+	astman_send_ack(s, m, "Launched bridge thread with success");
+
+	return 0;
+}
+
+static char *app_bridge = "Bridge";
+static char *bridge_synopsis = "Bridge two channels";
+static char *bridge_descrip =
+"Usage: Bridge(channel[,options])\n"
+"	Allows the ability to bridge two channels via the dialplan.\n"
+"The current channel is bridged to the specified 'channel'.\n"
+"  Options:\n"
+"    p - Play a courtesy tone to 'channel'.\n"
+"This application sets the following channel variable upon completion:\n"
+" BRIDGERESULT    The result of the bridge attempt as a text string, one of\n"
+"           SUCCESS | FAILURE | LOOP | NONEXISTENT | INCOMPATIBLE\n";
+
+enum {
+	BRIDGE_OPT_PLAYTONE = (1 << 0),
+};
+
+AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
+	AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE)
+END_OPTIONS );
+
+/*!
+ * \brief Bridge channels
+ * \param chan
+ * \param data channel to bridge with.
+ * 
+ * Split data, check we aren't bridging with ourself, check valid channel,
+ * answer call if not already, check compatible channels, setup bridge config
+ * now bridge call, if transfered party hangs up return to PBX extension.
+*/
+static int bridge_exec(struct ast_channel *chan, void *data)
+{
+	struct ast_channel *current_dest_chan, *final_dest_chan;
+	char *tmp_data  = NULL;
+	struct ast_flags opts = { 0, };
+	struct ast_bridge_config bconfig = { { 0, }, };
+
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(dest_chan);
+		AST_APP_ARG(options);
+	);
+	
+	if (ast_strlen_zero(data)) {
+		ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
+		return -1;
+	}
+
+	tmp_data = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, tmp_data);
+	if (!ast_strlen_zero(args.options))
+		ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options);
+
+	/* avoid bridge with ourselves */
+	if (!strncmp(chan->name, args.dest_chan, 
+		strlen(chan->name) < strlen(args.dest_chan) ? 
+		strlen(chan->name) : strlen(args.dest_chan))) {
+		ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
+		manager_event(EVENT_FLAG_CALL, "BridgeExec",
+					"Response: Failed\r\n"
+					"Reason: Unable to bridge channel to itself\r\n"
+					"Channel1: %s\r\n"
+					"Channel2: %s\r\n",
+					chan->name, args.dest_chan);
+		pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
+		return 0;
+	}
+
+	/* make sure we have a valid end point */
+	if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan, 
+		strlen(args.dest_chan)))) {
+		ast_log(LOG_WARNING, "Bridge failed because channel %s does not exist or we "
+			"cannot get its lock\n", args.dest_chan);
+		manager_event(EVENT_FLAG_CALL, "BridgeExec",
+					"Response: Failed\r\n"
+					"Reason: Cannot grab end point\r\n"
+					"Channel1: %s\r\n"
+					"Channel2: %s\r\n", chan->name, args.dest_chan);
+		pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
+		return 0;
+	}
+	ast_channel_unlock(current_dest_chan);
+
+	/* answer the channel if needed */
+	if (current_dest_chan->_state != AST_STATE_UP)
+		ast_answer(current_dest_chan);
+
+	/* try to allocate a place holder where current_dest_chan will be placed */
+	if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
+		NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) {
+		ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
+		manager_event(EVENT_FLAG_CALL, "BridgeExec",
+					"Response: Failed\r\n"
+					"Reason: cannot create placeholder\r\n"
+					"Channel1: %s\r\n"
+					"Channel2: %s\r\n", chan->name, args.dest_chan);
+	}
+	do_bridge_masquerade(current_dest_chan, final_dest_chan);
+
+	/* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
+	/* try to make compatible, send error if we fail */
+	if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
+		ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
+		manager_event(EVENT_FLAG_CALL, "BridgeExec",
+					"Response: Failed\r\n"
+					"Reason: Could not make channels compatible for bridge\r\n"
+					"Channel1: %s\r\n"
+					"Channel2: %s\r\n", chan->name, final_dest_chan->name);
+		ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
+		pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
+		return 0;
+	}
+
+	/* Report that the bridge will be successfull */
+	manager_event(EVENT_FLAG_CALL, "BridgeExec",
+				"Response: Success\r\n"
+				"Channel1: %s\r\n"
+				"Channel2: %s\r\n", chan->name, final_dest_chan->name);
+
+	/* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */	
+	if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
+		if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
+			if (ast_waitstream(final_dest_chan, "") < 0)
+				ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
+		}
+	}
+	
+	/* do the bridge */
+	ast_bridge_call(chan, final_dest_chan, &bconfig);
+
+	/* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
+	pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
+	if (!ast_check_hangup(final_dest_chan)) {
+		ast_log(LOG_EVENT, "starting new PBX in %s,%s,%d for chan %s\n", 
+			final_dest_chan->context, final_dest_chan->exten, 
+			final_dest_chan->priority, final_dest_chan->name);
+
+		if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
+			ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
+			ast_hangup(final_dest_chan);
+		} else
+			ast_log(LOG_EVENT, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
+	} else {
+		ast_log(LOG_EVENT, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name);
+		ast_hangup(final_dest_chan);
+	}
+
+	return 0;
+}
 
 static int load_config(void) 
 {
@@ -3034,6 +3325,8 @@
 {
 	int res;
 	
+	ast_register_application(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip);
+
 	memset(parking_ext, 0, sizeof(parking_ext));
 	memset(parking_con, 0, sizeof(parking_con));
 
@@ -3048,6 +3341,7 @@
 		ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
 		ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
 			"Park a channel", mandescr_park); 
+		ast_manager_register2("Bridge", EVENT_FLAG_CALL, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge);
 	}
 
 	res |= ast_devstate_prov_add("Park", metermaidstate);
Index: apps/app_voicemail.c
diff -Nau apps/app_voicemail.c.orig apps/app_voicemail.c
--- apps/app_voicemail.c.orig	2009-04-25 02:38:20.343758775 +0200
+++ apps/app_voicemail.c	2009-04-25 19:56:25.287569363 +0200
@@ -115,6 +115,7 @@
 static char imapport[8];
 static char imapflags[128];
 static char imapfolder[64];
+static int  imapsubfold = 0;
 static char authuser[32];
 static char authpassword[42];
 
@@ -4313,6 +4314,7 @@
 	/* we must use mbox(x) folder names, and copy the message there */
 	/* simple. huh? */
 	char sequence[10];
+	char folder[256];
 	/* get the real IMAP message number for this message */
 	snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
 	if (option_debug > 2)
@@ -4323,11 +4325,21 @@
 	} else if (box == 0) {
 		mail_clearflag(vms->mailstream, sequence, "\\Seen");
 	}
-	if (!strcasecmp(mbox(0), vms->curbox) && (box == 0 || box == 1)) {
+	if ((!strcasecmp(mbox(0), vms->curbox) || \
+        !strcasecmp(mbox(1), vms->curbox)) && \
+        (box == 0 || box == 1)) {  /* Don't copy data, just change Seen flag */
 		ast_mutex_unlock(&vms->lock);
 		return 0;
-	} else {
-		int res = !mail_copy(vms->mailstream,sequence,(char *) mbox(box)); 
+	} else if (box > 1) {          /* Do copy data using INBOX or subfolder */
+		if (imapsubfold == 1)
+			snprintf(folder, sizeof(folder), "%s%c%s", imapfolder, delimiter, mbox(box));
+		else
+			strncpy(folder, mbox(box), sizeof(folder));
+		int res = !mail_copy(vms->mailstream,sequence,folder);
+		ast_mutex_unlock(&vms->lock);
+		return res;
+	} else {  /* Copy data to INBOX delegating new/old status to Seen flag */
+		int res = !mail_copy(vms->mailstream,sequence,imapfolder);
 		ast_mutex_unlock(&vms->lock);
 		return res;
 	}
@@ -7686,6 +7698,10 @@
 #ifndef IMAP_STORAGE
 				} else if (!cmd) {
 					vms.deleted[vms.curmsg] = 1;
+#else
+				} else if (!cmd && (folder_int(vms.curbox) > 1  || box > 1)) {
+					vms.deleted[vms.curmsg] = 1;  /* Enforce deletion after */
+					deleted = 1;                  /* successful copy op */
 #endif
 				} else {
 					vms.deleted[vms.curmsg] = 0;
@@ -8198,6 +8214,7 @@
 	const char *imap_port;
 	const char *imap_flags;
 	const char *imap_folder;
+	const char *imap_use_subfold;
 	const char *auth_user;
 	const char *auth_password;
 	const char *expunge_on_hangup;
@@ -8342,6 +8359,15 @@
 		} else {
 			ast_copy_string(imapfolder,"INBOX", sizeof(imapfolder));
 		}
+		/* IMAP saved (sub)folder location policy */
+		if ((imap_use_subfold = ast_variable_retrieve(cfg, "general", "imapsubfold"))) {
+			if (ast_false(imap_use_subfold))
+				imapsubfold = 0;
+			else
+				imapsubfold = 1;
+		} else {
+			imapsubfold = 0;
+		}
 
 		/* There is some very unorthodox casting done here. This is due
 		 * to the way c-client handles the argument passed in. It expects a 
