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