diff -r 3be96a4c8c18 -r f29abea29121 asterisk/asterisk.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/asterisk.patch Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,2265 @@ +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 ++ * Russell Bryant ++ * ++ * 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 ++ * \author Russell Bryant ++ * ++ * \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 ++ * ++ * 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 ++#endif ++ ++#include ++#include ++#include ++#include ++#if 0 ++#include ++#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 ++ * ++ * 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 ++#endif ++ ++#include ++#include ++#include ++#include ++#if 0 ++#include ++#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 ++ * ++ * 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 ++#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 + ++/* 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