# HG changeset patch # User Michael Schloh von Bennewitz # Date 1240827545 -7200 # Node ID f29abea29121f6586f46e25b4463230cfb247277 # Parent 3be96a4c8c184621bfd1956616675e52ff782cdf Import new package spec for introduction into repository. diff -r 3be96a4c8c18 -r f29abea29121 asterisk/amd.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/amd.conf Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,18 @@ +; +; Answering Machine Detection Configuration +; + +;[general] +;initial_silence = 2500 ; Maximum silence duration before the greeting. + ; If exceeded then MACHINE. +;greeting = 1500 ; Maximum length of a greeting. If exceeded then MACHINE. +;after_greeting_silence = 800 ; Silence after detecting a greeting. + ; If exceeded then HUMAN +;total_analysis_time = 5000 ; Maximum time allowed for the algorithm to decide + ; on a HUMAN or MACHINE +;min_word_length = 100 ; Minimum duration of Voice to considered as a word +;between_words_silence = 50 ; Minimum duration of silence after a word to consider + ; the audio what follows as a new word +;maximum_number_of_words = 3 ; Maximum number of words in the greeting. + ; If exceeded then MACHINE +;silence_threshold = 256 diff -r 3be96a4c8c18 -r f29abea29121 asterisk/asterisk.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/asterisk.conf Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,78 @@ +;; +;; asterisk.conf -- Asterisk main configuration file +;; + +;[directories] +; Make sure these directories have the right permissions if not +; running Asterisk as root + +; Where the configuration files (except for this one) are located +;astetcdir => /etc/asterisk + +; Where the Asterisk loadable modules are located +;astmoddir => /usr/lib/asterisk/modules + +; Where additional 'library' elements (scripts, etc.) are located +;astvarlibdir => /var/lib/asterisk + +; Where AGI scripts/programs are located +;astagidir => /var/lib/asterisk/agi-bin + +; Where spool directories are located +; Voicemail, monitor, dictation and other apps will create files here +; and outgoing call files (used with pbx_spool) must be placed here +;astspooldir => /var/spool/asterisk + +; Where the Asterisk process ID (pid) file should be created +;astrundir => /var/run/asterisk + +; Where the Asterisk log files should be created +;astlogdir => /var/log/asterisk + + +;[options] +;Under "options" you can enter configuration options +;that you also can set with command line options + +;verbose = 0 ; Verbosity level for logging (-v) +;debug = 3 ; Debug: "No" or value (1-4) +;nofork=yes | no ; Background execution disabled (-f) +;alwaysfork=yes | no ; Always background, even with -v or -d (-F) +;console= yes | no ; Console mode (-c) +;highpriority = yes | no ; Execute with high priority (-p) +;initcrypto = yes | no ; Initialize crypto at startup (-i) +;nocolor = yes | no ; Disable ANSI colors (-n) +;dumpcore = yes | no ; Dump core on failure (-g) +;quiet = yes | no ; Run quietly (-q) +;timestamp = yes | no ; Force timestamping in CLI verbose output (-T) +;runuser = asterisk ; User to run asterisk as (-U) NOTE: will require changes to + ; directory and device permissions +;rungroup = asterisk ; Group to run asterisk as (-G) +;internal_timing = yes | no ; Enable internal timing support (-I) + +;These options have no command line equivalent +;cache_record_files = yes | no ; Cache record() files in another directory until completion +;record_cache_dir = +;transcode_via_sln = yes | no ; Build transcode paths via SLINEAR +;transmit_silence_during_record = yes | no ; send SLINEAR silence while channel is being recorded +;maxload = 1.0 ; The maximum load average we accept calls for +;maxcalls = 255 ; The maximum number of concurrent calls you want to allow +;execincludes = yes | no ; Allow #exec entries in configuration files +;dontwarn = yes | no ; Don't over-inform the Asterisk sysadm, he's a guru +;systemname = ; System name. Used to prefix CDR uniqueid and to fill ${SYSTEMNAME} +;languageprefix = yes | no ; Should language code be last component of sound file name or first? + ; when off, sound files are searched as // + ; when on, sound files are search as // + ; (only affects relative paths for sound files) + +;[files] +; Changing the following lines may compromise your security +; Asterisk.ctl is the pipe that is used to connect the remote CLI +; (asterisk -r) to Asterisk. Changing these settings change the +; permissions and ownership of this file. +; The file is created when Asterisk starts, in the "astrundir" above. + +;astctlpermissions = 0660 +;astctlowner = root +;astctlgroup = asterisk +;astctl = asterisk.ctl 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 diff -r 3be96a4c8c18 -r f29abea29121 asterisk/asterisk.patch.parseavp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/asterisk.patch.parseavp Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,17 @@ +Index: channels/chan_sip.c +diff -Nau channels/chan_sip.c.orig channels/chan_sip.c +--- channels/chan_sip.c.orig 2009-04-24 00:54:30.000000000 +0200 ++++ channels/chan_sip.c 2009-04-24 00:56:15.000000000 +0200 +@@ -5214,8 +5214,10 @@ + + numberofports = 1; + len = -1; +- if ((sscanf(m, "audio %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || +- (sscanf(m, "audio %d RTP/AVP %n", &x, &len) == 1 && len > 0)) { ++ if (((sscanf(m, "audio %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2) && (len > 0)) || ++ ((sscanf(m, "audio %d/%d RTP/SAVP %n", &x, &numberofports, &len) == 2) && (len > 0)) || ++ ((sscanf(m, "audio %d RTP/AVP %n", &x, &len) == 1) && (len > 0)) || ++ ((sscanf(m, "audio %d RTP/SAVP %n", &x, &len) == 1) && (len > 0))) { + audio = TRUE; + numberofmediastreams++; + /* Found audio stream in this media definition */ diff -r 3be96a4c8c18 -r f29abea29121 asterisk/asterisk.patch.proxymwi --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/asterisk.patch.proxymwi Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,24 @@ +Index: channels/chan_sip.c +diff -Nau channels/chan_sip.c.orig channels/chan_sip.c +--- channels/chan_sip.c.orig 2009-04-24 00:51:58.000000000 +0200 ++++ channels/chan_sip.c 2009-04-24 00:52:33.000000000 +0200 +@@ -16428,6 +16428,7 @@ + /* Called with peerl lock, but releases it */ + struct sip_pvt *p; + int newmsgs, oldmsgs; ++ char *s = NULL; + + /* Do we have an IP address? If not, skip this peer */ + if (!peer->addr.sin_addr.s_addr && !peer->defaddr.sin_addr.s_addr) +@@ -16461,6 +16462,11 @@ + /* Recalculate our side, and recalculate Call ID */ + if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip)) + p->ourip = __ourip; ++ /* Set the username = mailbox and remove the context */ ++ ast_string_field_build(p, username, "%s", peer->name); ++ s = strchr(p->username, '@'); ++ if (s != NULL) ++ *s = 0; + build_via(p); + build_callid_pvt(p); + /* Destroy this session after 32 secs */ diff -r 3be96a4c8c18 -r f29abea29121 asterisk/asterisk.patch.xfersips --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/asterisk.patch.xfersips Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,36 @@ +Index: channels/chan_sip.c +diff -Nau channels/chan_sip.c.orig channels/chan_sip.c +--- channels/chan_sip.c.orig 2009-04-24 00:48:57.000000000 +0200 ++++ channels/chan_sip.c 2009-04-24 00:49:21.000000000 +0200 +@@ -18771,6 +18771,7 @@ + \todo Fix this function so that we wait for reply to the REFER and + react to errors, denials or other issues the other end might have. + */ ++/* MSvB: Paramater dest may be SIPS encoded, having '@@' before host */ + static int sip_sipredirect(struct sip_pvt *p, const char *dest) + { + char *cdest; +@@ -18780,7 +18781,7 @@ + cdest = ast_strdupa(dest); + + extension = strsep(&cdest, "@"); +- host = strsep(&cdest, ":"); ++ host = strsep(&cdest, ":"); /* MSvB: Could begin with '@' if SIPS */ + port = strsep(&cdest, ":"); + if (ast_strlen_zero(extension)) { + ast_log(LOG_ERROR, "Missing mandatory argument: extension\n"); +@@ -18813,7 +18814,13 @@ + } + } + +- ast_string_field_build(p, our_contact, "Transfer ", extension, host, port ? ":" : "", port ? port : ""); ++ if (host && *host == '@') { ++ ast_log(LOG_DEBUG, "Decoding TLS incapable Asterisk SIP URI to a standard SIPS URI before redirecting via 302 Moved Temporarily\n"); ++ ast_string_field_build(p, our_contact, "Transfer ", extension, host + 1, port ? ":" : "", port ? port : ""); ++ } ++ else ++ ast_string_field_build(p, our_contact, "Transfer ", extension, host, port ? ":" : "", port ? port : ""); ++ + transmit_response_reliable(p, "302 Moved Temporarily", &p->initreq); + + sip_scheddestroy(p, SIP_TRANS_TIMEOUT); /* Make sure we stop send this reply. */ diff -r 3be96a4c8c18 -r f29abea29121 asterisk/asterisk.spec --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/asterisk.spec Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,544 @@ +## +## asterisk.spec -- OpenPKG RPM Package Specification +## Copyright (c) 2000-2007 OpenPKG Foundation e.V. +## Copyright (c) 2000-2007 Ralf S. Engelschall +## +## Permission to use, copy, modify, and distribute this software for +## any purpose with or without fee is hereby granted, provided that +## the above copyright notice and this permission notice appear in all +## copies. +## +## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +## SUCH DAMAGE. +## + +# package component versions +%define V_langsounds 1.4.12 +%define V_extrasounds 1.4.9 +%define V_amoomasounds 1.4 +%define V_customsounds 1.0 +%define V_chan_capi 1.1.2 + +# package information +Name: asterisk +Summary: Private Branch Exchange (PBX) for VoIP +URL: http://www.asterisk.org/ +Vendor: Mark Spencer et al. +Packager: Michael Schloh von Bennewitz +Distribution: Michael Schloh von Bennewitz +Class: EVAL +Group: VoIP +License: GPL +Version: 1.4.24.1 +Release: 20090422 + +# package options +%option with_libpri yes +%option with_xfersips yes +%option with_proxymwi yes +%option with_parseavp yes +%option with_radius no +%option with_sqlite no +%option with_pgsql no +%option with_curl no +%option with_imap no +%option with_astman no +%option with_capi no +%option with_zaptel no +%option with_smdipoll 10 + +# list of sources +Source0: http://downloads.digium.com/pub/asterisk/releases/asterisk-%{version}.tar.gz +Source1: ftp://ftp.chan-capi.org/chan-capi/chan_capi-%{V_chan_capi}.tar.gz +Source2: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-moh-freeplay-alaw.tar.gz +Source3: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-moh-freeplay-g722.tar.gz +Source4: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-moh-freeplay-g729.tar.gz +Source5: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-moh-freeplay-gsm.tar.gz +Source6: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-moh-freeplay-ulaw.tar.gz +Source7: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-extra-sounds-en-alaw-%{V_extrasounds}.tar.gz +Source8: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-extra-sounds-en-g722-%{V_extrasounds}.tar.gz +Source9: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-extra-sounds-en-g729-%{V_extrasounds}.tar.gz +Source10: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-extra-sounds-en-gsm-%{V_extrasounds}.tar.gz +Source11: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-extra-sounds-en-ulaw-%{V_extrasounds}.tar.gz +Source12: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-en-alaw-%{V_langsounds}.tar.gz +Source13: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-en-g722-%{V_langsounds}.tar.gz +Source14: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-en-g729-%{V_langsounds}.tar.gz +Source15: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-en-gsm-%{V_langsounds}.tar.gz +Source16: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-en-ulaw-%{V_langsounds}.tar.gz +Source17: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-es-alaw-%{V_langsounds}.tar.gz +Source18: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-es-g722-%{V_langsounds}.tar.gz +Source19: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-es-g729-%{V_langsounds}.tar.gz +Source20: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-es-gsm-%{V_langsounds}.tar.gz +Source21: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-es-ulaw-%{V_langsounds}.tar.gz +Source22: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-fr-alaw-%{V_langsounds}.tar.gz +Source23: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-fr-g722-%{V_langsounds}.tar.gz +Source24: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-fr-g729-%{V_langsounds}.tar.gz +Source25: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-fr-gsm-%{V_langsounds}.tar.gz +Source26: http://downloads.digium.com/pub/telephony/sounds/releases/asterisk-core-sounds-fr-ulaw-%{V_langsounds}.tar.gz +Source27: http://www.amooma.de/asterisk/sprachbausteine/asterisk-%{V_amoomasounds}-de-prompts.tar.gz +Source28: http://www.amooma.de/asterisk/sprachbausteine/asterisk-core-sounds-de-gsm-current.tar.gz +Source29: ftp://ftp.europalab.com/pub/sfw/machsnds/de-digits/de-digits-%{V_customsounds}.tar.bz2 +Source30: asterisk.conf +Source31: amd.conf +Source32: capi.conf +Source33: cdr.conf +Source34: cdr_custom.conf +Source35: codecs.conf +Source36: dundi.conf +Source37: enum.conf +Source38: extensions.conf +Source39: features.conf +Source40: festival.conf +Source41: followme.conf +Source42: indications.conf +Source33: logger.conf +Source34: manager.conf +Source45: meetme.conf +Source46: misdn.conf +Source47: modules.conf +Source48: musiconhold.conf +Source49: privacy.conf +Source50: rpt.conf +Source51: rtp.conf +Source52: say.conf +Source53: sip.conf +Source54: sip_notify.conf +Source55: sla.conf +Source56: voicemail.conf +Source57: zapata.conf +Source58: rc.asterisk +Source59: wakeup.agi +Patch0: asterisk.patch +Patch1: asterisk.patch.xfersips +Patch2: asterisk.patch.proxymwi +Patch3: asterisk.patch.parseavp + +# build information +Prefix: %{l_prefix} +BuildRoot: %{l_buildroot} +BuildPreReq: OpenPKG, openpkg >= 20040130, pkgconfig, awk, grep +PreReq: OpenPKG, openpkg >= 20040130 +BuildPreReq: ncurses, openssl, zlib +PreReq: ncurses, openssl, zlib +BuildPreReq: speex, vorbis-libs, sox +PreReq: speex, vorbis-libs, sox +%if "%{with_libpri}" == "yes" +BuildPreReq: libpri +PreReq: libpri +%endif +%if "%{with_radius}" == "yes" +BuildPreReq: radiusclient +PreReq: radiusclient +%endif +%if "%{with_sqlite}" == "yes" +BuildPreReq: sqlite +PreReq: sqlite +%endif +%if "%{with_pgsql}" == "yes" +BuildPreReq: postgresql +PreReq: postgresql +%endif +%if "%{with_curl}" == "yes" +BuildPreReq: curl +PreReq: curl +%endif +%if "%{with_imap}" == "yes" +BuildPreReq: imap +PreReq: imap +%endif +%if "%{with_astman}" == "yes" +BuildPreReq: newt +PreReq: newt +%endif +AutoReq: no +AutoReqProv: no + +%description + Asterisk is a complete Private Branch Exchange (PBX) in software. + It provides all of the features you would expect from a PBX and + more. Asterisk does Voice over IP (VoIP) in many protocols. Asterisk + provides Voicemail services with Directory, Call Conferencing, + Interactive Voice Response and Call Queuing. It has support for + three-way calling, caller ID services, ADSI, SIP, etc. Asterisk + needs no additional hardware for VoIP. + + This copy of Asterisk is optionally patched to allow the asterisk + server to respond to SIP/TLS transfer requests using the Transfer() + application. Should this option be chosen, the asterisk server + successfully dispatches all transfer destinations using 'SIPS' + technology by means of the standard SIP/2.0 302 Moved Temporarily + message, with a URI resembling . + + This copy of Asterisk is optionally patched as well to enclose the + correct user name in NOTIFY messages when MWI logic detects changes + in the state of Messages-Waiting. Asterisk will send NOTIFY messages + with the URI 'user@hostname' instead of simply 'hostname'. This can + be used by a external SIP proxy to route the MWI to the correct phone. + +%track + prog asterisk = { + version = %{version} + url = http://downloads.digium.com/pub/asterisk/releases/ + regex = asterisk-(__VER__)\.tar\.gz + } + +%prep + %setup -q -n asterisk-%{version} + %setup -q -n asterisk-%{version} -D -T -a 1 + %patch -p0 +%if "%{with_xfersips}" == "yes" + %patch -p0 -P 1 +%endif +%if "%{with_proxymwi}" == "yes" + %patch -p0 -P 2 +%endif +%if "%{with_parseavp}" == "yes" + %patch -p0 -P 3 +%endif + + # link install-sh to where Makefiles expect it + for dir in agi utils res channels pbx apps codecs formats cdr funcs main; do + ( cd $dir && ln -s ../install-sh ) || exit $? + done + + # apply corrections + case "%{l_platform -t}" in + *-sunos* ) + %{l_shtool} subst \ + -e 's|\(tmp->tm_gmtoff = ttisp->tt_gmtoff;\)|/*\1*/|' \ + main/stdtime/localtime.c + ;; + esac + %{l_shtool} subst \ + -e 's;sysconfdir=/etc;true;' \ + -e 's;mandir=/usr/share/man;true;' \ + -e 's;localstatedir=/var;true;' \ + -e 's;\(radiusclient\)-ng;\1;g' \ + -e 's;\(\-lsqlite\);\13;g' \ + -e 's;\(sqlite\)\(\.h\);\13\2;g' \ + -e 's;\(sqlite\)\(_exec\);\13\2;g' \ + -e 's;^\(LIBS="-lvorbis\);\1 ${OGG_LIB};' \ + -e 's;\(#include <\${NCURSES_DIR}/include\);\1/ncurses;' \ + -e 's;-I${IMAP_TK_DIR}/c-client;-I${IMAP_TK_DIR}/include/imap;g' \ + -e 's;${IMAP_TK_DIR}/c-client/c-client\.a;-limap -lssl -lcrypto -lcrypt;g' \ + configure + %{l_shtool} subst \ + -e 's; *-I/usr/local/ssl/include;;g' \ + -e 's;/opt/ssl/include;%{l_prefix}/include;g' \ + -e 's;/usr/local;%{l_prefix};g' \ + -e 's;^\(MOD_SUBDIR_CFLAGS=.*\ *\)$;\1 -I%{l_prefix}/include;' \ + -e 's;^\( *ASTETCDIR\)=.*;\1=$(sysconfdir)/asterisk;g' \ + -e 's;^\( *ASTLIBDIR\)=.*;\1=$(libdir)/asterisk;g' \ + -e 's;^\( *ASTHEADERDIR\)=.*;\1=$(includedir)/asterisk;g' \ + -e 's;^\( *ASTBINDIR\)=.*;\1=$(bindir);g' \ + -e 's;^\( *ASTSBINDIR\)=.*;\1=$(sbindir);g' \ + -e 's;^\( *ASTSPOOLDIR\)=.*;\1=$(localstatedir)/asterisk/spool;g' \ + -e 's;^\( *ASTLOGDIR\)=.*;\1=$(localstatedir)/asterisk/log;g' \ + -e 's;^\( *ASTVARRUNDIR\)=.*;\1=$(localstatedir)/asterisk/run;g' \ + -e 's;^\( *ASTMANDIR\)=.*;\1=$(mandir);g' \ + -e 's;^\( *ASTVARLIBDIR\)=.*;\1=$(localstatedir)/asterisk/lib;g' \ + -e 's;^\( *ASTVARRUNDIR\)=.*;\1=$(localstatedir)/asterisk/run;g' \ + -e 's;^\( *ASTDATADIR\):*=.*;\1=$(datadir)/asterisk;g' \ + -e 's/\(for f in\) \(\$(OLDMODS); do \\\)$/\1 "warning:" \2/' \ + Makefile + #-e 's;\(ASTSPOOLDIR=\$(localstatedir)\)\(/spool\)\(/asterisk\);\1\3\2;' \ + #-e 's;\(ASTLOGDIR=\$(localstatedir)\)\(/log\)\(/asterisk\);\1\3\2;' \ + #-e 's;\(ASTVARRUNDIR=\$(localstatedir)\)\(/run\);\1/asterisk\2;' \ + #-e 's;\(ASTVARRUNDIR=\$(localstatedir)\)\(/run\)\(/asterisk\);\1\3\2;' \ + #-e 's;\(ASTVARLIBDIR=\$(localstatedir)\)\(/lib\)\(/asterisk\);\1\3\2;' \ + #-e 's;\(ASTDATADIR:=\)\$(ASTVARLIBDIR);\1$(prefix)/share/asterisk;' \ + #Makefile + %{l_shtool} subst \ + -e 's; *-L/usr/local/ssl/lib;;g' \ + -e 's;/opt/ssl/lib;%{l_prefix}/lib;g' \ + -e 's;/usr/local;%{l_prefix};g' \ + -e 's;\(ASTLINK=\)$;\1-Wl,--export-dynamic;g' \ + main/Makefile + %{l_shtool} subst \ + -e 's;LOG_WARNING\(, "Failed to perform seek\);LOG_DEBUG\1;g' \ + main/channel.c + %{l_shtool} subst \ + -e 's;LOG_WARNING\(, "[^ ][^ ]* is not supported\);LOG_DEBUG\1;g' \ + formats/format_ogg_vorbis.c + %{l_shtool} subst \ + -e 's;\(/etc/radiusclient-ng/radiusclient.conf\);%{l_prefix}\1;g' \ + -e 's;\(radiusclient\)-ng;\1;g' \ + cdr/cdr_radius.c + %{l_shtool} subst \ + -e 's;\(sqlite\)\(\.h\);\13\2;g' \ + cdr/cdr_sqlite.c + %{l_shtool} subst \ + -e 's;\(#define DEFAULT_POLLING_INTERVAL\) *.*;\1 %{with_smdipoll};' \ + res/res_smdi.c + %{l_shtool} subst \ + -e 's;\(ASTERISK_HEADER_DIR=\).*;\1%{l_prefix}/include;g' \ + -e 's;\(MODULES_DIR=\).*;\1%{l_prefix}/lib/asterisk/modules;g' \ + -e 's;\(CONFIG_DIR=\).*;\1%{l_prefix}/etc/asterisk;g' \ + -e 's;\(\$(MODULES_DIR)\);$(DESTDIR)\1;g' \ + -e 's;\${CONFIG_DIR};$(DESTDIR)$(CONFIG_DIR);g' \ + chan_capi-%{V_chan_capi}/Makefile + +# # optionally specify CPU +# %{l_shtool} subst \ +# -e 's;build_cpu=\$1;build_cpu=i586;' \ +# -e 's;host_cpu=\$1;host_cpu=i586;' \ +# configure + +%build + # apply platform build rules + libs="`pkg-config openssl speex --libs-only-l`" +%if "%{with_curl}" == "yes" + libs="$libs `pkg-config libcurl --libs-only-l`" +%endif +%if "%{with_sqlite}" == "yes" + libs="$libs `pkg-config sqlite3 --libs-only-l`" +%endif +%if "%{with_pgsql}" == "yes" + libs="-lpq $libs" +%endif +%if "%{with_radius}" == "yes" + libs="$libs -lradiusclient" +%endif +%if "%{with_libpri}" == "yes" + libs="$libs -lpri" +%endif + case "%{l_platform -t}" in + *-linux* ) libs="$libs -lrt" ;; + *-sunos* ) libs="$libs -lrt" ;; + esac + + # configure package + CC="%{l_cc}" \ + CFLAGS="%{l_cflags -O}" \ +%if "%{with_imap}" == "yes" + CPPFLAGS="%{l_cppflags imap ncurses}" \ +%else + CPPFLAGS="%{l_cppflags ncurses}" \ +%endif + LDFLAGS="%{l_ldflags}" \ + LIBS="$libs" \ + ./configure \ + --prefix=%{l_prefix} \ + --mandir=%{l_prefix}/man \ + --with-ncurses=%{l_prefix} \ +%if "%{with_libpri}" == "yes" + --with-pri=%{l_prefix} \ +%else + --with-pri=no \ +%endif + --with-ssl=%{l_prefix} \ +%if "%{with_radius}" == "yes" + --with-radius=%{l_prefix} \ +%else + --with-radius=no \ +%endif +%if "%{with_sqlite}" == "yes" + --with-sqlite=%{l_prefix} \ +%else + --with-sqlite=no \ +%endif +%if "%{with_postgresql}" == "yes" + --with-postgres=%{l_prefix} \ +%else + --with-postgres=no \ +%endif +%if "%{with_curl}" == "yes" + --with-curl=%{l_prefix} \ +%else + --with-curl=no \ +%endif +%if "%{with_imap}" == "yes" + --with-imap=%{l_prefix} \ + --disable-largefile \ +%else + --with-imap=no \ +%endif +%if "%{with_astman}" == "yes" + --with-newt=%{l_prefix} \ +%else + --with-newt=no \ +%endif + --with-speex=%{l_prefix} \ + --with-speexdsp=%{l_prefix} \ + --with-ogg=%{l_prefix} \ + --with-vorbis=%{l_prefix} \ + --with-z=%{l_prefix} + + # build package + %{l_make} %{l_mflags -O} menuselect/menuselect menuselect-tree + menuselect/menuselect --check-deps menuselect.makeopts + %{l_shtool} subst \ + -e 's;\(MENUSELECT_MOH=\).*;\1;' \ + -e 's;\(MENUSELECT_CORE_SOUNDS=\).*;\1;' \ + -e 's;\(MENUSELECT_EXTRA_SOUNDS=\).*;\1;' \ + menuselect.makeopts +%if "%{with_imap}" == "yes" + %{l_shtool} subst \ + -e 's;\(MENUSELECT_OPTS_app_voicemail=\)$;\1IMAP_STORAGE;' \ + menuselect.makeopts +%endif + %{l_make} %{l_mflags -O} EXTLIBS="$libs" NOISY_BUILD=yes +%if "%{with_capi}" == "yes" + ( cd chan_capi-%{V_chan_capi} + %{l_make} %{l_mflags -O} + ) || exit $? +%endif + +%install + rm -rf $RPM_BUILD_ROOT + + # install package + %{l_make} %{l_mflags} install DESTDIR=$RPM_BUILD_ROOT +%if "%{with_capi}" == "yes" + ( cd chan_capi-%{V_chan_capi} + %{l_make} %{l_mflags} install samples DESTDIR=$RPM_BUILD_ROOT + ) || exit $? +%endif + + # install all sound prompt files + for codec in alaw ulaw g722 g729 gsm; do + for lang in es fr; do + ( cd $RPM_BUILD_ROOT%{l_prefix}/share/asterisk/sounds/${lang} + %{l_tar} zxf %{_sourcedir}/asterisk-core-sounds-${lang}-${codec}-%{V_langsounds}.tar.gz + ) || exit $? + done + ( cd $RPM_BUILD_ROOT%{l_prefix}/share/asterisk/sounds + %{l_tar} zxf %{_sourcedir}/asterisk-extra-sounds-en-${codec}-%{V_extrasounds}.tar.gz + %{l_tar} zxf %{_sourcedir}/asterisk-core-sounds-en-${codec}-%{V_langsounds}.tar.gz + ) || exit $? + done + + # install special case sound files + ( cd $RPM_BUILD_ROOT%{l_prefix}/share/asterisk/sounds + %{l_tar} jxf %{SOURCE de-digits-%{V_customsounds}.tar.bz2} + %{l_tar} zxf %{SOURCE asterisk-core-sounds-de-gsm-current.tar.gz} + cd de + %{l_tar} zxf %{_sourcedir}/asterisk-%{V_amoomasounds}-de-prompts.tar.gz + mv -f de/* . && rm -rf de + mv -f dictate/de/* letters/ && rm -rf dictate/de + mv -f digits/de/* letters/ && rm -rf digits/de + mv -f letters/de/* letters/ && rm -rf letters/de + mv -f phonetic/de/* letters/ && rm -rf phonetic/de + ) || exit $? + + # install additional music on hold files + ( cd $RPM_BUILD_ROOT%{l_prefix}/share/asterisk/moh + for codec in alaw ulaw g722 g729 gsm; do + %{l_tar} zxf %{_sourcedir}/asterisk-moh-freeplay-${codec}.tar.gz + done + ) || exit $? + +# # install nonstandard voicemail prompts +# %{l_shtool} mkdir -f -p -m 755 \ +# $RPM_BUILD_ROOT%{l_prefix}/var/asterisk/spool/voicemail/default/%{exten}/unavail +# %{l_shtool} install -c -m 660 \ +# %{_sourcedir}/ansage-%{V_ansage}.wav} \ +# $RPM_BUILD_ROOT%{l_prefix}/var/asterisk/spool/voicemail/default/%{exten}/unavail.wav + + # install default configuration + %{l_shtool} install -c -m 660 %{l_value -s -a} \ + %{SOURCE asterisk.conf} \ + %{SOURCE amd.conf} \ + %{SOURCE cdr.conf} \ + %{SOURCE codecs.conf} \ + %{SOURCE extensions.conf} \ + %{SOURCE features.conf} \ + %{SOURCE festival.conf} \ + %{SOURCE followme.conf} \ + %{SOURCE indications.conf} \ + %{SOURCE logger.conf} \ + %{SOURCE manager.conf} \ + %{SOURCE meetme.conf} \ + %{SOURCE modules.conf} \ + %{SOURCE musiconhold.conf} \ + %{SOURCE rtp.conf} \ + %{SOURCE sip.conf} \ + %{SOURCE sla.conf} \ + %{SOURCE voicemail.conf} \ + %{SOURCE zapata.conf} \ + $RPM_BUILD_ROOT%{l_prefix}/etc/asterisk/ + + # install runcommand script + %{l_shtool} mkdir -f -p -m 755 \ + $RPM_BUILD_ROOT%{l_prefix}/etc/rc.d + %{l_shtool} install -c -m 755 %{l_value -s -a} \ + %{SOURCE rc.asterisk} $RPM_BUILD_ROOT%{l_prefix}/etc/rc.d/ + + # install additional AGI scripts + %{l_shtool} install -c -m 755 %{l_value -s -a} \ + %{SOURCE wakeup.agi} $RPM_BUILD_ROOT%{l_prefix}/share/asterisk/agi-bin/ + + # correct installation hierarchy + %{l_shtool} mkdir -f -p -m 755 \ + $RPM_BUILD_ROOT%{l_prefix}/var/asterisk/lib \ + $RPM_BUILD_ROOT%{l_prefix}/var/asterisk/spool/outgoing + + # remove unused components + rm -rf \ + $RPM_BUILD_ROOT%{l_prefix}/bin \ + $RPM_BUILD_ROOT%{l_prefix}/share/asterisk/images \ + $RPM_BUILD_ROOT%{l_prefix}/share/asterisk/sounds/de/.DS_Store \ + $RPM_BUILD_ROOT%{l_prefix}/share/asterisk/sounds/de/autogen.sh \ + >/dev/null 2>&1 || true + + # adjust inconsistent names + for bin in $RPM_BUILD_ROOT%{l_prefix}/share/asterisk/agi-bin/*.*; do + mv $bin `echo $bin | sed -e 's;\.[^.]*$;;'` + done + + # strip down installation + strip $RPM_BUILD_ROOT%{l_prefix}/bin/* \ + $RPM_BUILD_ROOT%{l_prefix}/sbin/* \ + $RPM_BUILD_ROOT%{l_prefix}/lib/asterisk/modules/* \ + $RPM_BUILD_ROOT%{l_prefix}/share/asterisk/agi-bin/* \ + >/dev/null 2>&1 || true + + # determine installation files + %{l_rpmtool} files -v -ofiles -r$RPM_BUILD_ROOT %{l_files_std} \ + '%config %attr(660,%{l_musr},%{l_rgrp}) %{l_prefix}/etc/asterisk/*' \ + '%config %attr(644,%{l_musr},%{l_mgrp}) %{l_prefix}/share/asterisk/sounds/de/*' \ + '%config %attr(755,%{l_musr},%{l_mgrp}) %{l_prefix}/share/asterisk/sounds/de/dictate' \ + '%config %attr(755,%{l_musr},%{l_mgrp}) %{l_prefix}/share/asterisk/sounds/de/digits' \ + '%config %attr(755,%{l_musr},%{l_mgrp}) %{l_prefix}/share/asterisk/sounds/de/followme' \ + '%config %attr(755,%{l_musr},%{l_mgrp}) %{l_prefix}/share/asterisk/sounds/de/letters' \ + '%config %attr(755,%{l_musr},%{l_mgrp}) %{l_prefix}/share/asterisk/sounds/de/phonetic' \ + '%attr(-,%{l_rusr},%{l_rgrp}) %{l_prefix}/var/asterisk/*' \ + '%attr(-,%{l_rusr},%{l_rgrp}) %{l_prefix}/var/asterisk/*/*' + +%files -f files + +%clean + rm -rf $RPM_BUILD_ROOT + +%post + # after upgrade, restart service + [ $1 -eq 2 ] || exit 0 + eval `%{l_rc} asterisk status 2>/dev/null` + [ ".$asterisk_active" = .yes ] && %{l_rc} asterisk restart + exit 0 + +%preun + # before erase, stop service and remove log files + [ $1 -eq 0 ] || exit 0 + %{l_rc} asterisk stop 2>/dev/null + rm -f $RPM_INSTALL_PREFIX/var/asterisk/lib/* >/dev/null 2>&1 || true + rm -f $RPM_INSTALL_PREFIX/var/asterisk/log/* >/dev/null 2>&1 || true + rm -f $RPM_INSTALL_PREFIX/var/asterisk/log/cdr-*/* >/dev/null 2>&1 || true + rm -f $RPM_INSTALL_PREFIX/var/asterisk/run/* >/dev/null 2>&1 || true + for deldir in meetme outgoing system tmp; do + rm -rf \ + $RPM_INSTALL_PREFIX/var/asterisk/spool/$deldir \ + >/dev/null 2>&1 || true + done + exit 0 + diff -r 3be96a4c8c18 -r f29abea29121 asterisk/capi.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/capi.conf Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,34 @@ +;; +;; capi.conf -- Asterisk ISDN/CAPI channel configuration +;; + +;[general] +;nationalprefix = 0 +;internationalprefix = 00 +;rxgain = 1.0 +;txgain = 1.0 +;ulaw = no +;debug = yes + +;[ISDN1] +;isdnmode = msn +;incomingmsn = * +;controller = 0 +;group = 1 +;;prefix = 0 +;softdtmf = off +;relaxdtmf = off +;accountcode = +;context = external +;holdtype = local +;immediate = yes +;echocancel = no +;echosquelch = no +;echotail = 64 +;bridge = yes +;callgroup = 1 +;deflect = 1234567 +;devices = 2 +;wait_silence_samples = 1000 +;dtmf_generate = yes + diff -r 3be96a4c8c18 -r f29abea29121 asterisk/cdr.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/cdr.conf Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,148 @@ +; +; Asterisk Call Detail Record engine configuration +; +; CDR is Call Detail Record, which provides logging services via a variety of +; pluggable backend modules. Detailed call information can be recorded to +; databases, files, etc. Useful for billing, fraud prevention, compliance with +; Sarbanes-Oxley aka The Enron Act, QOS evaluations, and more. +; + +;[general] + +; Define whether or not to use CDR logging. Setting this to "no" will override +; any loading of backend CDR modules. Default is "yes". +;enable=yes + +; Define whether or not to log unanswered calls. Setting this to "yes" will +; report every attempt to ring a phone in dialing attempts, when it was not +; answered. For example, if you try to dial 3 extensions, and this option is "yes", +; you will get 3 CDR's, one for each phone that was rung. Default is "no". Some +; find this information horribly useless. Others find it very valuable. Note, in "yes" +; mode, you will see one CDR, with one of the call targets on one side, and the originating +; channel on the other, and then one CDR for each channel attempted. This may seem +; redundant, but cannot be helped. +;unanswered = no + +; Define the CDR batch mode, where instead of posting the CDR at the end of +; every call, the data will be stored in a buffer to help alleviate load on the +; asterisk server. Default is "no". +; +; WARNING WARNING WARNING +; Use of batch mode may result in data loss after unsafe asterisk termination +; ie. software crash, power failure, kill -9, etc. +; WARNING WARNING WARNING +; +;batch=no + +; Define the maximum number of CDRs to accumulate in the buffer before posting +; them to the backend engines. 'batch' must be set to 'yes'. Default is 100. +;size=100 + +; Define the maximum time to accumulate CDRs in the buffer before posting them +; to the backend engines. If this time limit is reached, then it will post the +; records, regardless of the value defined for 'size'. 'batch' must be set to +; 'yes'. Note that time is in seconds. Default is 300 (5 minutes). +;time=300 + +; The CDR engine uses the internal asterisk scheduler to determine when to post +; records. Posting can either occur inside the scheduler thread, or a new +; thread can be spawned for the submission of every batch. For small batches, +; it might be acceptable to just use the scheduler thread, so set this to "yes". +; For large batches, say anything over size=10, a new thread is recommended, so +; set this to "no". Default is "no". +;scheduleronly=no + +; When shutting down asterisk, you can block until the CDRs are submitted. If +; you don't, then data will likely be lost. You can always check the size of +; the CDR batch buffer with the CLI "cdr status" command. To enable blocking on +; submission of CDR data during asterisk shutdown, set this to "yes". Default +; is "yes". +;safeshutdown=yes + +; Normally, CDR's are not closed out until after all extensions are finished +; executing. By enabling this option, the CDR will be ended before executing +; the "h" extension so that CDR values such as "end" and "billsec" may be +; retrieved inside of of this extension. +;endbeforehexten=no + +; +; +; CHOOSING A CDR "BACKEND" (what kind of output to generate) +; +; To choose a backend, you have to make sure either the right category is +; defined in this file, or that the appropriate config file exists, and has the +; proper definitions in it. If there are any problems, usually, the entry will +; silently ignored, and you get no output. +; +; Also, please note that you can generate CDR records in as many formats as you +; wish. If you configure 5 different CDR formats, then each event will be logged +; in 5 different places! In the example config files, all formats are commented +; out except for the cdr-csv format. +; +; Here are all the possible back ends: +; +; csv, custom, manager, odbc, pgsql, radius, sqlite, tds +; (also, mysql is available via the asterisk-addons, due to licensing +; requirements) +; (please note, also, that other backends can be created, by creating +; a new backend module in the source cdr/ directory!) +; +; Some of the modules required to provide these backends will not build or install +; unless some dependency requirements are met. Examples of this are pgsql, odbc, +; etc. If you are not getting output as you would expect, the first thing to do +; is to run the command "make menuselect", and check what modules are available, +; by looking in the "2. Call Detail Recording" option in the main menu. If your +; backend is marked with XXX, you know that the "configure" command could not find +; the required libraries for that option. +; +; To get CDRs to be logged to the plain-jane /var/log/asterisk/cdr-csv/Master.csv +; file, define the [csv] category in this file. No database necessary. The example +; config files are set up to provide this kind of output by default. +; +; To get custom csv CDR records, make sure the cdr_custom.conf file +; is present, and contains the proper [mappings] section. The advantage to +; using this backend, is that you can define which fields to output, and in +; what order. By default, the example configs are set up to mimic the cdr-csv +; output. If you don't make any changes to the mappings, you are basically generating +; the same thing as cdr-csv, but expending more CPU cycles to do so! +; +; To get manager events generated, make sure the cdr_manager.conf file exists, +; and the [general] section is defined, with the single variable 'enabled = yes'. +; +; For odbc, make sure all the proper libs are installed, that "make menuselect" +; shows that the modules are available, and the cdr_odbc.conf file exists, and +; has a [global] section with the proper variables defined. +; +; For pgsql, make sure all the proper libs are installed, that "make menuselect" +; shows that the modules are available, and the cdr_pgsql.conf file exists, and +; has a [global] section with the proper variables defined. +; +; For logging to radius databases, make sure all the proper libs are installed, that +; "make menuselect" shows that the modules are available, and the [radius] +; category is defined in this file, and in that section, make sure the 'radiuscfg' +; variable is properly pointing to an existing radiusclient.conf file. +; +; For logging to sqlite databases, make sure the 'cdr.db' file exists in the log directory, +; which is usually /var/log/asterisk. Of course, the proper libraries should be available +; during the 'configure' operation. +; +; For tds logging, make sure the proper libraries are available during the 'configure' +; phase, and that cdr_tds.conf exists and is properly set up with a [global] category. +; +; Also, remember, that if you wish to log CDR info to a database, you will have to define +; a specific table in that databse to make things work! See the doc directory for more details +; on how to create this table in each database. +; + +;[csv] +;usegmtime=yes ; log date/time in GMT. Default is "no" +;loguniqueid=yes ; log uniqueid. Default is "no +;loguserfield=yes ; log user field. Default is "no + +;[radius] +;usegmtime=yes ; log date/time in GMT +;loguniqueid=yes ; log uniqueid +;loguserfield=yes ; log user field +; Set this to the location of the radiusclient-ng configuration file +; The default is /etc/radiusclient-ng/radiusclient.conf +;radiuscfg => /usr/local/etc/radiusclient-ng/radiusclient.conf diff -r 3be96a4c8c18 -r f29abea29121 asterisk/cdr_custom.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/cdr_custom.conf Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,10 @@ +; +; Mappings for custom config file +; +; to get your csv output in a format tailored to your liking, uncomment the following +; and look for the output in the cdr-custom/Master.csv file (usually in /var/log/asterisk). +; +; +;[mappings] +;Master.csv => "${CDR(clid)}","${CDR(src)}","${CDR(dst)}","${CDR(dcontext)}","${CDR(channel)}","${CDR(dstchannel)}","${CDR(lastapp)}","${CDR(lastdata)}","${CDR(start)}","${CDR(answer)}","${CDR(end)}","${CDR(duration)}","${CDR(billsec)}","${CDR(disposition)}","${CDR(amaflags)}","${CDR(accountcode)}","${CDR(uniqueid)}","${CDR(userfield)}" + diff -r 3be96a4c8c18 -r f29abea29121 asterisk/codecs.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/codecs.conf Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,65 @@ +;[speex] +; CBR encoding quality [0..10] +; used only when vbr = false +;quality => 3 + +; codec complexity [0..10] +; tradeoff between cpu/quality +;complexity => 2 + +; perceptual enhancement [true / false] +; improves clarity of decoded speech +;enhancement => true + +; voice activity detection [true / false] +; reduces bitrate when no voice detected, used only for CBR +; (implicit in VBR/ABR) +;vad => true + +; variable bit rate [true / false] +; uses bit rate proportionate to voice complexity +;vbr => true + +; available bit rate [bps, 0 = off] +; encoding quality modulated to match this target bit rate +; not recommended with dtx or pp_vad - may cause bandwidth spikes +;abr => 0 + +; VBR encoding quality [0-10] +; floating-point values allowed +;vbr_quality => 4 + +; discontinuous transmission [true / false] +; stops transmitting completely when silence is detected +; pp_vad is far more effective but more CPU intensive +;dtx => false + +; preprocessor configuration +; these options only affect Speex v1.1.8 or newer + +; enable preprocessor [true / false] +; allows dsp functionality below but incurs CPU overhead +;preprocess => false + +; preproc voice activity detection [true / false] +; more advanced equivalent of DTX, based on voice frequencies +;pp_vad => false + +; preproc automatic gain control [true / false] +;pp_agc => false +;pp_agc_level => 8000 + +; preproc denoiser [true / false] +;pp_denoise => false + +; preproc dereverb [true / false] +;pp_dereverb => false +;pp_dereverb_decay => 0.4 +;pp_dereverb_level => 0.3 + + +;[plc] +; for all codecs which do not support native PLC +; this determines whether to perform generic PLC +; there is a minor performance penalty for this +;genericplc => true diff -r 3be96a4c8c18 -r f29abea29121 asterisk/dundi.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/dundi.conf Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,239 @@ +; +; DUNDi configuration file +; +; For more information about DUNDi, see http://www.dundi.com +; +; +;[general] +; +; The "general" section contains general parameters relating +; to the operation of the dundi client and server. +; +; The first part should be your complete contact information +; should someone else in your peer group need to contact you. +; +;department=Your Department +;organization=Your Company, Inc. +;locality=Your City +;stateprov=ST +;country=US +;email=your@email.com +;phone=+12565551212 +; +; +; Specify bind address and port number. Default is +; 4520 +; +;bindaddr=0.0.0.0 +;port=4520 +; +; Our entity identifier (Should generally be the MAC address of the +; machine it's running on. Defaults to the first eth address, but you +; can override it here, as long as you set it to the MAC of *something* +; you own!) +; +;entityid=00:07:E9:3B:76:60 +; +; Peers shall cache our query responses for the specified time, +; given in seconds. Default is 3600. +; +;cachetime=3600 +; +; This defines the max depth in which to search the DUNDi system. +; Note that the maximum time that we will wait for a response is +; (2000 + 200 * ttl) ms. +; +;ttl=32 +; +; If we don't get ACK to our DPDISCOVER within 2000ms, and autokill is set +; to yes, then we cancel the whole thing (that's enough time for one +; retransmission only). This is used to keep things from stalling for a long +; time for a host that is not available, but would be ill advised for bad +; connections. In addition to 'yes' or 'no' you can also specify a number +; of milliseconds. See 'qualify' for individual peers to turn on for just +; a specific peer. +; +;autokill=yes +; +; pbx_dundi creates a rotating key called "secret", under the family +; 'secretpath'. The default family is dundi (resulting in +; the key being held at dundi/secret). +; +;secretpath=dundi +; +; The 'storehistory' option (also changeable at runtime with +; 'dundi store history' and 'dundi no store history') will +; cause the DUNDi engine to keep track of the last several +; queries and the amount of time each query took to execute +; for the purpose of tracking slow nodes. This option is +; off by default due to performance impacts. +; +;storehistory=yes + +;[mappings] +; +; The "mappings" section maps DUNDi contexts +; to contexts on the local asterisk system. Remember +; that numbers that are made available under the e164 +; DUNDi context are regulated by the DUNDi General Peering +; Agreement (GPA) if you are a member of the DUNDi E.164 +; Peering System. +; +; dundi_context => local_context,weight,tech,dest[,options]] +; +; 'dundi_context' is the name of the context being requested +; within the DUNDi request +; +; 'local_context' is the name of the context on the local system +; in which numbers can be looked up for which responses shall be given. +; +; 'weight' is the weight to use for the responses provided from this +; mapping. The number must be >= 0 and < 60000. Since it is totally +; valid to receive multiple responses to a query, responses received +; with a lower weight are tried first. Note that the weight has a +; special meaning in the e164 context - see the GPA for more details. +; +; 'tech' is the technology to use (IAX, SIP, H323) +; +; 'dest' is the destination to supply for reaching that number. The +; following variables can be used in the destination string and will +; be automatically substituted: +; ${NUMBER}: The number being requested +; ${IPADDR}: The IP address to connect to +; ${SECRET}: The current rotating secret key to be used +; +; Further options may include: +; +; nounsolicited: No unsolicited calls of any type permitted via this +; route +; nocomunsolicit: No commercial unsolicited calls permitted via +; this route +; residential: This number is known to be a residence +; commercial: This number is known to be a business +; mobile: This number is known to be a mobile phone +; nocomunsolicit: No commercial unsolicited calls permitted via +; this route +; nopartial: Do not search for partial matches +; +; There *must* exist an entry in mappings for DUNDi to respond +; to any request, although it may be empty. +; +;e164 => dundi-e164-canonical,0,IAX2,dundi:${SECRET}@${IPADDR}/${NUMBER},nounsolicited,nocomunsolicit,nopartial +;e164 => dundi-e164-customers,100,IAX2,dundi:${SECRET}@${IPADDR}/${NUMBER},nounsolicited,nocomunsolicit,nopartial +;e164 => dundi-e164-via-pstn,400,IAX2,dundi:${SECRET}@${IPADDR}/${NUMBER},nounsolicited,nocomunsolicit,nopartial + +;digexten => default,0,IAX2,guest@lappy/${NUMBER} +;asdf => + + +; +; +; The remaining sections represent the peers +; that we fundamentally trust. The section name +; represents the name and optionally at a specific +; DUNDi context if you want the trust to be established +; for only a specific DUNDi context. +; +; inkey - What key they will be authenticating to us with +; +; outkey - What key we use to authenticate to them +; +; host - What their host is +; +; order - What search order to use. May be 'primary', 'secondary', +; 'tertiary' or 'quartiary'. In large systems, it is beneficial +; to only query one up-stream host in order to maximize caching +; value. Adding one with primary and one with secondary gives you +; redundancy without sacrificing performance. +; +; include - Includes this peer when searching a particular context +; for lookup (set "all" to perform all lookups with that +; host. This is also the context in which peers are permitted +; to precache. +; +; noinclude - Disincludes this peer when searching a particular context +; for lookup (set "all" to perform no lookups with that +; host. +; +; permit - Permits this peer to search a given DUNDi context on +; the local system. Set "all" to permit this host to +; lookup all contexts. This is also a context for which +; we will create/forward PRECACHE commands. +; +; deny - Denies this peer to search a given DUNDi context on +; the local system. Set "all" to deny this host to +; lookup all contexts. +; +; model - inbound, outbound, or symmetric for whether we receive +; requests only, transmit requests only, or do both. +; +; precache - Utilize/Permit precaching with this peer (to pre +; cache means to provide an answer when no request +; was made and is used so that machines with few +; routes can push those routes up a to a higher level). +; outgoing means we send precache routes to this peer, +; incoming means we permit this peer to send us +; precache routes. symmetric means we do both. +; +; Note: You cannot mix symmetric/outbound model with symmetric/inbound +; precache, nor can you mix symmetric/inbound model with symmetric/outbound +; precache. +; +; +; The '*' peer is special and matches an unspecified entity +; + +; +; Sample Primary e164 DUNDi peer +; +;[00:50:8B:F3:75:BB] +;model = symmetric +;host = 64.215.96.114 +;inkey = digium +;outkey = misery +;include = e164 +;permit = e164 +;qualify = yes + +; +; Sample Secondary e164 DUNDi peer +; +;[00:A0:C9:96:92:84] +;model = symmetric +;host = misery.digium.com +;inkey = misery +;outkey = ourkey +;include = e164 +;permit = e164 +;qualify = yes +;order = secondary + +; +; Sample "push mode" downstream host +; +;[00:0C:76:96:75:28] +;model = inbound +;host = dynamic +;precache = inbound +;inkey = littleguy +;outkey = ourkey +;include = e164 ; In this case used only for precaching +;permit = e164 +;qualify = yes + +; +; Sample "push mode" upstream host +; +;[00:07:E9:3B:76:60] +;model = outbound +;precache = outbound +;host = 216.207.245.34 +;register = yes +;inkey = dhcp34 +;permit = all ; In this case used only for precaching +;include = all +;qualify = yes +;outkey=foo + +;[*] +; diff -r 3be96a4c8c18 -r f29abea29121 asterisk/enum.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/enum.conf Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,22 @@ +; +; ENUM Configuration for resolving phone numbers over DNS +; +; Sample config for Asterisk +; This file is reloaded at "module reload enum" in the CLI +; +;[general] +; +; The search list for domains may be customized. Domains are searched +; in the order they are listed here. +; +;search => e164.arpa +; +; If you'd like to use the E.164.org public ENUM registry in addition +; to the official e164.arpa one, uncomment the following line +; +;search => e164.org +; +; As there are more H323 drivers available you have to select to which +; drive a H323 URI will map. Default is "H323". +; +;h323driver => H323 diff -r 3be96a4c8c18 -r f29abea29121 asterisk/extensions.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asterisk/extensions.conf Mon Apr 27 12:19:05 2009 +0200 @@ -0,0 +1,614 @@ +; extensions.conf - the Asterisk dial plan +; +; Static extension configuration file, used by +; the pbx_config module. This is where you configure all your +; inbound and outbound calls in Asterisk. +; +; This configuration file is reloaded +; - With the "dialplan reload" command in the CLI +; - With the "reload" command (that reloads everything) in the CLI + +; +; The "General" category is for certain variables. +; +;[general] +; +; If static is set to no, or omitted, then the pbx_config will rewrite +; this file when extensions are modified. Remember that all comments +; made in the file will be lost when that happens. +; +; XXX Not yet implemented XXX +; +;static=yes +; +; if static=yes and writeprotect=no, you can save dialplan by +; CLI command "dialplan save" too +; +;writeprotect=no +; +; If autofallthrough is set, then if an extension runs out of +; things to do, it will terminate the call with BUSY, CONGESTION +; or HANGUP depending on Asterisk's best guess. This is the default. +; +; If autofallthrough is not set, then if an extension runs out of +; things to do, Asterisk will wait for a new extension to be dialed +; (this is the original behavior of Asterisk 1.0 and earlier). +; +;autofallthrough=no +; +; If clearglobalvars is set, global variables will be cleared +; and reparsed on an extensions reload, or Asterisk reload. +; +; If clearglobalvars is not set, then global variables will persist +; through reloads, and even if deleted from the extensions.conf or +; one of its included files, will remain set to the previous value. +; +; NOTE: A complication sets in, if you put your global variables into +; the AEL file, instead of the extensions.conf file. With clearglobalvars +; set, a "reload" will often leave the globals vars cleared, because it +; is not unusual to have extensions.conf (which will have no globals) +; load after the extensions.ael file (where the global vars are stored). +; So, with "reload" in this particular situation, first the AEL file will +; clear and then set all the global vars, then, later, when the extensions.conf +; file is loaded, the global vars are all cleared, and then not set, because +; they are not stored in the extensions.conf file. +; +;clearglobalvars=no +; +; If priorityjumping is set to 'yes', then applications that support +; 'jumping' to a different priority based on the result of their operations +; will do so (this is backwards compatible behavior with pre-1.2 releases +; of Asterisk). Individual applications can also be requested to do this +; by passing a 'j' option in their arguments. +; +;priorityjumping=yes +; +; User context is where entries from users.conf are registered. The +; default value is 'default' +; +;userscontext=default +; +; You can include other config files, use the #include command +; (without the ';'). Note that this is different from the "include" command +; that includes contexts within other contexts. The #include command works +; in all asterisk configuration files. +;#include "filename.conf" + +; The "Globals" category contains global variables that can be referenced +; in the dialplan with the GLOBAL dialplan function: +; ${GLOBAL(VARIABLE)} +; ${${GLOBAL(VARIABLE)}} or ${text${GLOBAL(VARIABLE)}} or any hybrid +; Unix/Linux environmental variables can be reached with the ENV dialplan +; function: ${ENV(VARIABLE)} +; +;[globals] +;CONSOLE=Console/dsp ; Console interface for demo +;CONSOLE=Zap/1 +;CONSOLE=Phone/phone0 +;IAXINFO=guest ; IAXtel username/password +;IAXINFO=myuser:mypass +;TRUNK=Zap/G2 ; Trunk interface +; +; Note the 'G2' in the TRUNK variable above. It specifies which group (defined +; in zapata.conf) to dial, i.e. group 2, and how to choose a channel to use in +; the specified group. The four possible options are: +; +; g: select the lowest-numbered non-busy Zap channel +; (aka. ascending sequential hunt group). +; G: select the highest-numbered non-busy Zap channel +; (aka. descending sequential hunt group). +; r: use a round-robin search, starting at the next highest channel than last +; time (aka. ascending rotary hunt group). +; R: use a round-robin search, starting at the next lowest channel than last +; time (aka. descending rotary hunt group). +; +;TRUNKMSD=1 ; MSD digits to strip (usually 1 or 0) +;TRUNK=IAX2/user:pass@provider + +; +; Any category other than "General" and "Globals" represent +; extension contexts, which are collections of extensions. +; +; Extension names may be numbers, letters, or combinations +; thereof. If an extension name is prefixed by a '_' +; character, it is interpreted as a pattern rather than a +; literal. In patterns, some characters have special meanings: +; +; X - any digit from 0-9 +; Z - any digit from 1-9 +; N - any digit from 2-9 +; [1235-9] - any digit in the brackets (in this example, 1,2,3,5,6,7,8,9) +; . - wildcard, matches anything remaining (e.g. _9011. matches +; anything starting with 9011 excluding 9011 itself) +; ! - wildcard, causes the matching process to complete as soon as +; it can unambiguously determine that no other matches are possible +; +; For example the extension _NXXXXXX would match normal 7 digit dialings, +; while _1NXXNXXXXXX would represent an area code plus phone number +; preceded by a one. +; +; Each step of an extension is ordered by priority, which must +; always start with 1 to be considered a valid extension. The priority +; "next" or "n" means the previous priority plus one, regardless of whether +; the previous priority was associated with the current extension or not. +; The priority "same" or "s" means the same as the previously specified +; priority, again regardless of whether the previous entry was for the +; same extension. Priorities may be immediately followed by a plus sign +; and another integer to add that amount (most useful with 's' or 'n'). +; Priorities may then also have an alias, or label, in +; parenthesis after their name which can be used in goto situations +; +; Contexts contain several lines, one for each step of each +; extension, which can take one of two forms as listed below, +; with the first form being preferred. +; +;[context] +;exten => someexten,{priority|label{+|-}offset}[(alias)],application(arg1,arg2,...) +;exten => someexten,{priority|label{+|-}offset}[(alias)],application,arg1|arg2... +; +; Included Contexts +; +; One may include another context in the current one as well, optionally with a +; date and time. Included contexts are included in the order +; they are listed. +; The reason a context would include other contexts is for their +; extensions. +; The algorithm to find an extension is recursive, and works in this +; fashion: +; first, given a stack on which to store context references, +; push the context to find the extension onto the stack... +; a) Try to find a matching extension in the context at the top of +; the stack, and, if found, begin executing the priorities +; there in sequence. +; b) If not found, Search the switches, if any declared, in +; sequence. +; c) If still not found, for each include, push that context onto +; the top of the context stack, and recurse to a). +; d) If still not found, pop the entry from the top of the stack; +; if the stack is empty, the search has failed. If it's not, +; continue with the next context in c). +; This is a depth-first traversal, and stops with the first context +; that provides a matching extension. As usual, if more than one +; pattern in a context will match, the 'best' match will win. +; Please note that that extensions found in an included context are +; treated as if they were in the context from which the search began. +; The PBX's notion of the "current context" is not changed. +; Please note that in a context, it does not matter where an include +; directive occurs. Whether at the top, or near the bottom, the effect +; will be the same. The only thing that matters is that if there is +; more than one include directive, they will be searched for extensions +; in order, first to last. +; Also please note that pattern matches (like _9XX) are not treated +; any differently than exact matches (like 987). Also note that the +; order of extensions in a context have no affect on the outcome. +; +; Timing list for includes is +; +;