Fri, 15 Oct 2010 19:06:09 +0200
Correct shared library and plugin link logic, as well as informal text.
Update file server URL, update build resource estimations, correct RPATH
logic, allow for qmake(1) static to shared library changes via CONFIG
argument, correct documentation broken title and index links, correct
shared library install path, install only one set of (correct) plugins,
install the designer shared library (as required by QtCreator), announce
features related to shared linking using qmake(1), and correclty
substitute hard coded paths in prl and la library files.
michael@202 | 1 | Index: cdr/cdr_sqlite.c |
michael@202 | 2 | diff -Nau cdr/cdr_sqlite.c.orig cdr/cdr_sqlite.c |
michael@202 | 3 | --- cdr/cdr_sqlite.c.orig 2007-06-14 23:50:40.000000000 +0200 |
michael@202 | 4 | +++ cdr/cdr_sqlite.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 5 | @@ -58,7 +58,7 @@ |
michael@202 | 6 | #define DATE_FORMAT "%Y-%m-%d %T" |
michael@202 | 7 | |
michael@202 | 8 | static char *name = "sqlite"; |
michael@202 | 9 | -static sqlite* db = NULL; |
michael@202 | 10 | +static sqlite3 *db = NULL; |
michael@202 | 11 | |
michael@202 | 12 | AST_MUTEX_DEFINE_STATIC(sqlite_lock); |
michael@202 | 13 | |
michael@202 | 14 | @@ -92,10 +92,10 @@ |
michael@202 | 15 | static int sqlite_log(struct ast_cdr *cdr) |
michael@202 | 16 | { |
michael@202 | 17 | int res = 0; |
michael@202 | 18 | - char *zErr = 0; |
michael@202 | 19 | struct tm tm; |
michael@202 | 20 | time_t t; |
michael@202 | 21 | char startstr[80], answerstr[80], endstr[80]; |
michael@202 | 22 | + char *cdrsql = 0; |
michael@202 | 23 | int count; |
michael@202 | 24 | |
michael@202 | 25 | ast_mutex_lock(&sqlite_lock); |
michael@202 | 26 | @@ -113,7 +113,7 @@ |
michael@202 | 27 | strftime(endstr, sizeof(endstr), DATE_FORMAT, &tm); |
michael@202 | 28 | |
michael@202 | 29 | for(count=0; count<5; count++) { |
michael@202 | 30 | - res = sqlite_exec_printf(db, |
michael@202 | 31 | + cdrsql = sqlite3_mprintf( |
michael@202 | 32 | "INSERT INTO cdr (" |
michael@202 | 33 | "clid,src,dst,dcontext," |
michael@202 | 34 | "channel,dstchannel,lastapp,lastdata, " |
michael@202 | 35 | @@ -138,8 +138,7 @@ |
michael@202 | 36 | # if LOG_USERFIELD |
michael@202 | 37 | ",'%q'" |
michael@202 | 38 | # endif |
michael@202 | 39 | - ")", NULL, NULL, &zErr, |
michael@202 | 40 | - cdr->clid, cdr->src, cdr->dst, cdr->dcontext, |
michael@202 | 41 | + ")", cdr->clid, cdr->src, cdr->dst, cdr->dcontext, |
michael@202 | 42 | cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata, |
michael@202 | 43 | startstr, answerstr, endstr, |
michael@202 | 44 | cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags, |
michael@202 | 45 | @@ -151,16 +150,13 @@ |
michael@202 | 46 | ,cdr->userfield |
michael@202 | 47 | # endif |
michael@202 | 48 | ); |
michael@202 | 49 | + res = sqlite3_exec(db, cdrsql, 0, 0, 0); |
michael@202 | 50 | + sqlite3_free(cdrsql); |
michael@202 | 51 | if (res != SQLITE_BUSY && res != SQLITE_LOCKED) |
michael@202 | 52 | break; |
michael@202 | 53 | usleep(200); |
michael@202 | 54 | } |
michael@202 | 55 | |
michael@202 | 56 | - if (zErr) { |
michael@202 | 57 | - ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr); |
michael@202 | 58 | - free(zErr); |
michael@202 | 59 | - } |
michael@202 | 60 | - |
michael@202 | 61 | ast_mutex_unlock(&sqlite_lock); |
michael@202 | 62 | return res; |
michael@202 | 63 | } |
michael@202 | 64 | @@ -168,7 +164,7 @@ |
michael@202 | 65 | static int unload_module(void) |
michael@202 | 66 | { |
michael@202 | 67 | if (db) |
michael@202 | 68 | - sqlite_close(db); |
michael@202 | 69 | + sqlite3_close(db); |
michael@202 | 70 | ast_cdr_unregister(name); |
michael@202 | 71 | return 0; |
michael@202 | 72 | } |
michael@202 | 73 | @@ -181,17 +177,16 @@ |
michael@202 | 74 | |
michael@202 | 75 | /* is the database there? */ |
michael@202 | 76 | snprintf(fn, sizeof(fn), "%s/cdr.db", ast_config_AST_LOG_DIR); |
michael@202 | 77 | - db = sqlite_open(fn, 0660, &zErr); |
michael@202 | 78 | + sqlite3_open(fn, &db); |
michael@202 | 79 | if (!db) { |
michael@202 | 80 | - ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr); |
michael@202 | 81 | - free(zErr); |
michael@202 | 82 | + ast_log(LOG_ERROR, "cdr_sqlite: %s\n", sqlite3_errmsg(db)); |
michael@202 | 83 | return -1; |
michael@202 | 84 | } |
michael@202 | 85 | |
michael@202 | 86 | /* is the table there? */ |
michael@202 | 87 | - res = sqlite_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL); |
michael@202 | 88 | + res = sqlite3_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL); |
michael@202 | 89 | if (res) { |
michael@202 | 90 | - res = sqlite_exec(db, sql_create_table, NULL, NULL, &zErr); |
michael@202 | 91 | + res = sqlite3_exec(db, sql_create_table, NULL, NULL, &zErr); |
michael@202 | 92 | if (res) { |
michael@202 | 93 | ast_log(LOG_ERROR, "cdr_sqlite: Unable to create table 'cdr': %s\n", zErr); |
michael@202 | 94 | free(zErr); |
michael@202 | 95 | @@ -210,7 +205,7 @@ |
michael@202 | 96 | |
michael@202 | 97 | err: |
michael@202 | 98 | if (db) |
michael@202 | 99 | - sqlite_close(db); |
michael@202 | 100 | + sqlite3_close(db); |
michael@202 | 101 | return -1; |
michael@202 | 102 | } |
michael@202 | 103 | |
michael@202 | 104 | Index: channels/chan_sip.c |
michael@202 | 105 | diff -Nau channels/chan_sip.c.orig channels/chan_sip.c |
michael@202 | 106 | --- channels/chan_sip.c.orig 2009-04-02 19:20:22.000000000 +0200 |
michael@202 | 107 | +++ channels/chan_sip.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 108 | @@ -7469,7 +7469,7 @@ |
michael@202 | 109 | |
michael@202 | 110 | ast_copy_string(from, get_header(&p->initreq, "From"), sizeof(from)); |
michael@202 | 111 | c = get_in_brackets(from); |
michael@202 | 112 | - if (strncasecmp(c, "sip:", 4)) { |
michael@202 | 113 | + if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) { |
michael@202 | 114 | ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c); |
michael@202 | 115 | return -1; |
michael@202 | 116 | } |
michael@202 | 117 | @@ -7477,7 +7477,7 @@ |
michael@202 | 118 | |
michael@202 | 119 | ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to)); |
michael@202 | 120 | c = get_in_brackets(to); |
michael@202 | 121 | - if (strncasecmp(c, "sip:", 4)) { |
michael@202 | 122 | + if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) { |
michael@202 | 123 | ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c); |
michael@202 | 124 | return -1; |
michael@202 | 125 | } |
michael@202 | 126 | @@ -8004,7 +8004,10 @@ |
michael@202 | 127 | of = get_in_brackets(from); |
michael@202 | 128 | ast_string_field_set(p, from, of); |
michael@202 | 129 | if (strncasecmp(of, "sip:", 4)) |
michael@202 | 130 | - ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); |
michael@202 | 131 | + if (strncasecmp(of, "sips:", 5)) |
michael@202 | 132 | + ast_log(LOG_NOTICE, "From address missing 'sip:' or 'sips:', using it anyway\n"); |
michael@202 | 133 | + else |
michael@202 | 134 | + of += 5; |
michael@202 | 135 | else |
michael@202 | 136 | of += 4; |
michael@202 | 137 | /* Get just the username part */ |
michael@202 | 138 | @@ -8280,7 +8283,10 @@ |
michael@202 | 139 | |
michael@202 | 140 | /* Make sure it's a SIP URL */ |
michael@202 | 141 | if (strncasecmp(contact, "sip:", 4)) { |
michael@202 | 142 | - ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", contact); |
michael@202 | 143 | + if (strncasecmp(contact, "sips:", 5)) |
michael@202 | 144 | + ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip: or sips:) trying to use anyway\n", contact); |
michael@202 | 145 | + else |
michael@202 | 146 | + contact += 5; |
michael@202 | 147 | } else |
michael@202 | 148 | contact += 4; |
michael@202 | 149 | |
michael@202 | 150 | @@ -8409,7 +8415,10 @@ |
michael@202 | 151 | |
michael@202 | 152 | /* Make sure it's a SIP URL */ |
michael@202 | 153 | if (strncasecmp(curi, "sip:", 4)) { |
michael@202 | 154 | - ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", curi); |
michael@202 | 155 | + if (strncasecmp(curi, "sips:", 5)) |
michael@202 | 156 | + ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip: or sips:) trying to use anyway\n", curi); |
michael@202 | 157 | + else |
michael@202 | 158 | + curi += 5; |
michael@202 | 159 | } else |
michael@202 | 160 | curi += 4; |
michael@202 | 161 | /* Ditch q */ |
michael@202 | 162 | @@ -9000,9 +9009,12 @@ |
michael@202 | 163 | |
michael@202 | 164 | if (!strncasecmp(c, "sip:", 4)) { |
michael@202 | 165 | name = c + 4; |
michael@202 | 166 | + } |
michael@202 | 167 | + else if (!strncasecmp(c, "sips:", 5)) { |
michael@202 | 168 | + name = c + 5; |
michael@202 | 169 | } else { |
michael@202 | 170 | name = c; |
michael@202 | 171 | - ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr)); |
michael@202 | 172 | + ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip: or sips:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr)); |
michael@202 | 173 | } |
michael@202 | 174 | |
michael@202 | 175 | /* Strip off the domain name */ |
michael@202 | 176 | @@ -9162,10 +9174,15 @@ |
michael@202 | 177 | return 0; |
michael@202 | 178 | c = get_in_brackets(tmp); |
michael@202 | 179 | if (strncasecmp(c, "sip:", 4)) { |
michael@202 | 180 | - ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", c); |
michael@202 | 181 | - return -1; |
michael@202 | 182 | + if (strncasecmp(c, "sips:", 5)) { |
michael@202 | 183 | + ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", c); |
michael@202 | 184 | + return -1; |
michael@202 | 185 | + } |
michael@202 | 186 | + else |
michael@202 | 187 | + c += 5; |
michael@202 | 188 | } |
michael@202 | 189 | - c += 4; |
michael@202 | 190 | + else |
michael@202 | 191 | + c += 4; |
michael@202 | 192 | a = c; |
michael@202 | 193 | strsep(&a, "@;"); /* trim anything after @ or ; */ |
michael@202 | 194 | if (sip_debug_test_pvt(p)) |
michael@202 | 195 | @@ -9200,10 +9217,15 @@ |
michael@202 | 196 | uri = get_in_brackets(tmp); |
michael@202 | 197 | |
michael@202 | 198 | if (strncasecmp(uri, "sip:", 4)) { |
michael@202 | 199 | - ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", uri); |
michael@202 | 200 | - return -1; |
michael@202 | 201 | + if (strncasecmp(uri, "sips:", 5)) { |
michael@202 | 202 | + ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", uri); |
michael@202 | 203 | + return -1; |
michael@202 | 204 | + } |
michael@202 | 205 | + else |
michael@202 | 206 | + uri += 5; |
michael@202 | 207 | } |
michael@202 | 208 | - uri += 4; |
michael@202 | 209 | + else |
michael@202 | 210 | + uri += 4; |
michael@202 | 211 | |
michael@202 | 212 | /* Now find the From: caller ID and name */ |
michael@202 | 213 | ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf)); |
michael@202 | 214 | @@ -9217,10 +9239,15 @@ |
michael@202 | 215 | |
michael@202 | 216 | if (!ast_strlen_zero(from)) { |
michael@202 | 217 | if (strncasecmp(from, "sip:", 4)) { |
michael@202 | 218 | - ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", from); |
michael@202 | 219 | - return -1; |
michael@202 | 220 | + if (strncasecmp(from, "sips:", 5)) { |
michael@202 | 221 | + ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", from); |
michael@202 | 222 | + return -1; |
michael@202 | 223 | + } |
michael@202 | 224 | + else |
michael@202 | 225 | + from += 5; |
michael@202 | 226 | } |
michael@202 | 227 | - from += 4; |
michael@202 | 228 | + else |
michael@202 | 229 | + from += 4; |
michael@202 | 230 | if ((a = strchr(from, '@'))) |
michael@202 | 231 | *a++ = '\0'; |
michael@202 | 232 | else |
michael@202 | 233 | @@ -9397,10 +9424,15 @@ |
michael@202 | 234 | ast_uri_decode(refer_to); |
michael@202 | 235 | |
michael@202 | 236 | if (strncasecmp(refer_to, "sip:", 4)) { |
michael@202 | 237 | - ast_log(LOG_WARNING, "Can't transfer to non-sip: URI. (Refer-to: %s)?\n", refer_to); |
michael@202 | 238 | - return -3; |
michael@202 | 239 | + if (strncasecmp(refer_to, "sips:", 5)) { |
michael@202 | 240 | + ast_log(LOG_WARNING, "Can't transfer to non-sip: URI. (Refer-to: %s)?\n", refer_to); |
michael@202 | 241 | + return -3; |
michael@202 | 242 | + } |
michael@202 | 243 | + else |
michael@202 | 244 | + refer_to += 5; /* Skip sips: */ |
michael@202 | 245 | } |
michael@202 | 246 | - refer_to += 4; /* Skip sip: */ |
michael@202 | 247 | + else |
michael@202 | 248 | + refer_to += 4; /* Skip sip: */ |
michael@202 | 249 | |
michael@202 | 250 | /* Get referred by header if it exists */ |
michael@202 | 251 | p_referred_by = get_header(req, "Referred-By"); |
michael@202 | 252 | @@ -9417,9 +9449,13 @@ |
michael@202 | 253 | } |
michael@202 | 254 | |
michael@202 | 255 | referred_by_uri = get_in_brackets(h_referred_by); |
michael@202 | 256 | - if(strncasecmp(referred_by_uri, "sip:", 4)) { |
michael@202 | 257 | - ast_log(LOG_WARNING, "Huh? Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri); |
michael@202 | 258 | - referred_by_uri = (char *) NULL; |
michael@202 | 259 | + if (strncasecmp(referred_by_uri, "sip:", 4)) { |
michael@202 | 260 | + if (strncasecmp(referred_by_uri, "sips:", 5)) { |
michael@202 | 261 | + ast_log(LOG_WARNING, "Huh? Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri); |
michael@202 | 262 | + referred_by_uri = (char *) NULL; |
michael@202 | 263 | + } |
michael@202 | 264 | + else |
michael@202 | 265 | + referred_by_uri += 5; /* Skip sips: */ |
michael@202 | 266 | } else { |
michael@202 | 267 | referred_by_uri += 4; /* Skip sip: */ |
michael@202 | 268 | } |
michael@202 | 269 | @@ -9547,10 +9583,15 @@ |
michael@202 | 270 | ast_uri_decode(c); |
michael@202 | 271 | |
michael@202 | 272 | if (strncasecmp(c, "sip:", 4)) { |
michael@202 | 273 | - ast_log(LOG_WARNING, "Huh? Not a SIP header in Also: transfer (%s)?\n", c); |
michael@202 | 274 | - return -1; |
michael@202 | 275 | + if (strncasecmp(c, "sips:", 5)) { |
michael@202 | 276 | + ast_log(LOG_WARNING, "Huh? Not a SIP header in Also: transfer (%s)?\n", c); |
michael@202 | 277 | + return -1; |
michael@202 | 278 | + } |
michael@202 | 279 | + else |
michael@202 | 280 | + c += 5; |
michael@202 | 281 | } |
michael@202 | 282 | - c += 4; |
michael@202 | 283 | + else |
michael@202 | 284 | + c += 4; |
michael@202 | 285 | if ((a = strchr(c, ';'))) /* Remove arguments */ |
michael@202 | 286 | *a = '\0'; |
michael@202 | 287 | |
michael@202 | 288 | @@ -9761,6 +9802,8 @@ |
michael@202 | 289 | t = uri2; |
michael@202 | 290 | if (!strncasecmp(t, "sip:", 4)) |
michael@202 | 291 | t+= 4; |
michael@202 | 292 | + else if (!strncasecmp(t, "sips:", 5)) |
michael@202 | 293 | + t+= 5; |
michael@202 | 294 | ast_string_field_set(p, exten, t); |
michael@202 | 295 | t = strchr(p->exten, '@'); |
michael@202 | 296 | if (t) |
michael@202 | 297 | @@ -9771,7 +9814,10 @@ |
michael@202 | 298 | /* save the URI part of the From header */ |
michael@202 | 299 | ast_string_field_set(p, from, of); |
michael@202 | 300 | if (strncasecmp(of, "sip:", 4)) { |
michael@202 | 301 | - ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); |
michael@202 | 302 | + if (strncasecmp(of, "sips:", 5)) |
michael@202 | 303 | + ast_log(LOG_NOTICE, "From address missing 'sip:' or 'sips:', using it anyway\n"); |
michael@202 | 304 | + else |
michael@202 | 305 | + of += 5; |
michael@202 | 306 | } else |
michael@202 | 307 | of += 4; |
michael@202 | 308 | /* Get just the username part */ |
michael@202 | 309 | @@ -12379,6 +12425,8 @@ |
michael@202 | 310 | if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) { |
michael@202 | 311 | if (!strncasecmp(s, "sip:", 4)) |
michael@202 | 312 | s += 4; |
michael@202 | 313 | + else if (!strncasecmp(s, "sips:", 5)) |
michael@202 | 314 | + s += 5; |
michael@202 | 315 | e = strchr(s, ';'); |
michael@202 | 316 | if (e) |
michael@202 | 317 | *e = '\0'; |
michael@202 | 318 | @@ -12404,6 +12452,8 @@ |
michael@202 | 319 | |
michael@202 | 320 | if (!strncasecmp(s, "sip:", 4)) |
michael@202 | 321 | s += 4; |
michael@202 | 322 | + else if (!strncasecmp(s, "sips:", 5)) |
michael@202 | 323 | + s += 5; |
michael@202 | 324 | if (option_debug > 1) |
michael@202 | 325 | ast_log(LOG_DEBUG, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain); |
michael@202 | 326 | if (p->owner) { |
michael@202 | 327 | Index: codecs/codec_g722.c |
michael@202 | 328 | diff -Nau codecs/codec_g722.c.orig codecs/codec_g722.c |
michael@202 | 329 | --- codecs/codec_g722.c.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 330 | +++ codecs/codec_g722.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 331 | @@ -0,0 +1,306 @@ |
michael@202 | 332 | +/* |
michael@202 | 333 | + * Asterisk -- An open source telephony toolkit. |
michael@202 | 334 | + * |
michael@202 | 335 | + * Copyright (C) 1999 - 2008, Digium, Inc. |
michael@202 | 336 | + * |
michael@202 | 337 | + * Matthew Fredrickson <creslin@digium.com> |
michael@202 | 338 | + * Russell Bryant <russell@digium.com> |
michael@202 | 339 | + * |
michael@202 | 340 | + * Special thanks to Steve Underwood for the implementation |
michael@202 | 341 | + * and for doing the 8khz<->g.722 direct translation code. |
michael@202 | 342 | + * |
michael@202 | 343 | + * See http://www.asterisk.org for more information about |
michael@202 | 344 | + * the Asterisk project. Please do not directly contact |
michael@202 | 345 | + * any of the maintainers of this project for assistance; |
michael@202 | 346 | + * the project provides a web site, mailing lists and IRC |
michael@202 | 347 | + * channels for your use. |
michael@202 | 348 | + * |
michael@202 | 349 | + * This program is free software, distributed under the terms of |
michael@202 | 350 | + * the GNU General Public License Version 2. See the LICENSE file |
michael@202 | 351 | + * at the top of the source tree. |
michael@202 | 352 | + */ |
michael@202 | 353 | + |
michael@202 | 354 | +/*! \file |
michael@202 | 355 | + * |
michael@202 | 356 | + * \brief codec_g722.c - translate between signed linear and ITU G.722-64kbps |
michael@202 | 357 | + * |
michael@202 | 358 | + * \author Matthew Fredrickson <creslin@digium.com> |
michael@202 | 359 | + * \author Russell Bryant <russell@digium.com> |
michael@202 | 360 | + * |
michael@202 | 361 | + * \arg http://soft-switch.org/downloads/non-gpl-bits.tgz |
michael@202 | 362 | + * \arg http://lists.digium.com/pipermail/asterisk-dev/2006-September/022866.html |
michael@202 | 363 | + * |
michael@202 | 364 | + * \ingroup codecs |
michael@202 | 365 | + */ |
michael@202 | 366 | + |
michael@202 | 367 | +#include "asterisk.h" |
michael@202 | 368 | + |
michael@202 | 369 | +ASTERISK_FILE_VERSION(__FILE__, "$Revision: 106501 $") |
michael@202 | 370 | + |
michael@202 | 371 | +#include "asterisk/linkedlists.h" |
michael@202 | 372 | +#include "asterisk/module.h" |
michael@202 | 373 | +#include "asterisk/config.h" |
michael@202 | 374 | +#include "asterisk/options.h" |
michael@202 | 375 | +#include "asterisk/translate.h" |
michael@202 | 376 | +#include "asterisk/utils.h" |
michael@202 | 377 | + |
michael@202 | 378 | +#define BUFFER_SAMPLES 8096 /* size for the translation buffers */ |
michael@202 | 379 | +#define BUF_SHIFT 5 |
michael@202 | 380 | + |
michael@202 | 381 | +/* Sample frame data */ |
michael@202 | 382 | + |
michael@202 | 383 | +#include "g722/g722.h" |
michael@202 | 384 | +#include "slin_g722_ex.h" |
michael@202 | 385 | +#include "g722_slin_ex.h" |
michael@202 | 386 | + |
michael@202 | 387 | +struct g722_encoder_pvt { |
michael@202 | 388 | + g722_encode_state_t g722; |
michael@202 | 389 | +}; |
michael@202 | 390 | + |
michael@202 | 391 | +struct g722_decoder_pvt { |
michael@202 | 392 | + g722_decode_state_t g722; |
michael@202 | 393 | +}; |
michael@202 | 394 | + |
michael@202 | 395 | +/*! \brief init a new instance of g722_encoder_pvt. */ |
michael@202 | 396 | +static int lintog722_new(struct ast_trans_pvt *pvt) |
michael@202 | 397 | +{ |
michael@202 | 398 | + struct g722_encoder_pvt *tmp = pvt->pvt; |
michael@202 | 399 | + |
michael@202 | 400 | + g722_encode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000); |
michael@202 | 401 | + |
michael@202 | 402 | + return 0; |
michael@202 | 403 | +} |
michael@202 | 404 | + |
michael@202 | 405 | +static int lin16tog722_new(struct ast_trans_pvt *pvt) |
michael@202 | 406 | +{ |
michael@202 | 407 | + struct g722_encoder_pvt *tmp = pvt->pvt; |
michael@202 | 408 | + |
michael@202 | 409 | + g722_encode_init(&tmp->g722, 64000, 0); |
michael@202 | 410 | + |
michael@202 | 411 | + return 0; |
michael@202 | 412 | +} |
michael@202 | 413 | + |
michael@202 | 414 | +/*! \brief init a new instance of g722_encoder_pvt. */ |
michael@202 | 415 | +static int g722tolin_new(struct ast_trans_pvt *pvt) |
michael@202 | 416 | +{ |
michael@202 | 417 | + struct g722_decoder_pvt *tmp = pvt->pvt; |
michael@202 | 418 | + |
michael@202 | 419 | + g722_decode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000); |
michael@202 | 420 | + |
michael@202 | 421 | + return 0; |
michael@202 | 422 | +} |
michael@202 | 423 | + |
michael@202 | 424 | +static int g722tolin16_new(struct ast_trans_pvt *pvt) |
michael@202 | 425 | +{ |
michael@202 | 426 | + struct g722_decoder_pvt *tmp = pvt->pvt; |
michael@202 | 427 | + |
michael@202 | 428 | + g722_decode_init(&tmp->g722, 64000, 0); |
michael@202 | 429 | + |
michael@202 | 430 | + return 0; |
michael@202 | 431 | +} |
michael@202 | 432 | + |
michael@202 | 433 | +static int g722tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) |
michael@202 | 434 | +{ |
michael@202 | 435 | + struct g722_decoder_pvt *tmp = pvt->pvt; |
michael@202 | 436 | + int out_samples; |
michael@202 | 437 | + int in_samples; |
michael@202 | 438 | + |
michael@202 | 439 | + /* g722_decode expects the samples to be in the invalid samples / 2 format */ |
michael@202 | 440 | + in_samples = f->samples / 2; |
michael@202 | 441 | + |
michael@202 | 442 | + out_samples = g722_decode(&tmp->g722, (int16_t *) &pvt->outbuf[pvt->samples * sizeof(int16_t)], |
michael@202 | 443 | + (uint8_t *) f->data, in_samples); |
michael@202 | 444 | + |
michael@202 | 445 | + pvt->samples += out_samples; |
michael@202 | 446 | + |
michael@202 | 447 | + pvt->datalen += (out_samples * sizeof(int16_t)); |
michael@202 | 448 | + |
michael@202 | 449 | + return 0; |
michael@202 | 450 | +} |
michael@202 | 451 | + |
michael@202 | 452 | +static int lintog722_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) |
michael@202 | 453 | +{ |
michael@202 | 454 | + struct g722_encoder_pvt *tmp = pvt->pvt; |
michael@202 | 455 | + int outlen; |
michael@202 | 456 | + |
michael@202 | 457 | + outlen = g722_encode(&tmp->g722, (uint8_t *) (&pvt->outbuf[pvt->datalen]), |
michael@202 | 458 | + (int16_t *) f->data, f->samples); |
michael@202 | 459 | + |
michael@202 | 460 | + pvt->samples += outlen * 2; |
michael@202 | 461 | + |
michael@202 | 462 | + pvt->datalen += outlen; |
michael@202 | 463 | + |
michael@202 | 464 | + return 0; |
michael@202 | 465 | +} |
michael@202 | 466 | + |
michael@202 | 467 | +static struct ast_frame *g722tolin_sample(void) |
michael@202 | 468 | +{ |
michael@202 | 469 | + static struct ast_frame f = { |
michael@202 | 470 | + .frametype = AST_FRAME_VOICE, |
michael@202 | 471 | + .subclass = AST_FORMAT_G722, |
michael@202 | 472 | + .datalen = sizeof(g722_slin_ex), |
michael@202 | 473 | + .samples = sizeof(g722_slin_ex) * 2, |
michael@202 | 474 | + .src = __PRETTY_FUNCTION__, |
michael@202 | 475 | + .data = g722_slin_ex, |
michael@202 | 476 | + }; |
michael@202 | 477 | + |
michael@202 | 478 | + return &f; |
michael@202 | 479 | +} |
michael@202 | 480 | + |
michael@202 | 481 | +static struct ast_frame *g722tolin16_sample(void) |
michael@202 | 482 | +{ |
michael@202 | 483 | + static struct ast_frame f = { |
michael@202 | 484 | + .frametype = AST_FRAME_VOICE, |
michael@202 | 485 | + .subclass = AST_FORMAT_G722, |
michael@202 | 486 | + .datalen = sizeof(slin_g722_ex), |
michael@202 | 487 | + .samples = sizeof(slin_g722_ex) * 2, |
michael@202 | 488 | + .src = __PRETTY_FUNCTION__, |
michael@202 | 489 | + .data = slin_g722_ex, |
michael@202 | 490 | + }; |
michael@202 | 491 | + |
michael@202 | 492 | + return &f; |
michael@202 | 493 | +} |
michael@202 | 494 | + |
michael@202 | 495 | +static struct ast_frame *lintog722_sample (void) |
michael@202 | 496 | +{ |
michael@202 | 497 | + static struct ast_frame f = { |
michael@202 | 498 | + .frametype = AST_FRAME_VOICE, |
michael@202 | 499 | + .subclass = AST_FORMAT_SLINEAR, |
michael@202 | 500 | + .datalen = sizeof(slin_g722_ex), |
michael@202 | 501 | + .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]), |
michael@202 | 502 | + .src = __PRETTY_FUNCTION__, |
michael@202 | 503 | + .data = slin_g722_ex, |
michael@202 | 504 | + }; |
michael@202 | 505 | + |
michael@202 | 506 | + return &f; |
michael@202 | 507 | +} |
michael@202 | 508 | + |
michael@202 | 509 | +static struct ast_frame *lin16tog722_sample (void) |
michael@202 | 510 | +{ |
michael@202 | 511 | + static struct ast_frame f = { |
michael@202 | 512 | + .frametype = AST_FRAME_VOICE, |
michael@202 | 513 | + .subclass = AST_FORMAT_SLINEAR16, |
michael@202 | 514 | + .datalen = sizeof(slin_g722_ex), |
michael@202 | 515 | + .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]), |
michael@202 | 516 | + .src = __PRETTY_FUNCTION__, |
michael@202 | 517 | + .data = slin_g722_ex, |
michael@202 | 518 | + }; |
michael@202 | 519 | + |
michael@202 | 520 | + return &f; |
michael@202 | 521 | +} |
michael@202 | 522 | + |
michael@202 | 523 | +static struct ast_translator g722tolin = { |
michael@202 | 524 | + .name = "g722tolin", |
michael@202 | 525 | + .srcfmt = AST_FORMAT_G722, |
michael@202 | 526 | + .dstfmt = AST_FORMAT_SLINEAR, |
michael@202 | 527 | + .newpvt = g722tolin_new, /* same for both directions */ |
michael@202 | 528 | + .framein = g722tolin_framein, |
michael@202 | 529 | + .sample = g722tolin_sample, |
michael@202 | 530 | + .desc_size = sizeof(struct g722_decoder_pvt), |
michael@202 | 531 | + .buffer_samples = BUFFER_SAMPLES / sizeof(int16_t), |
michael@202 | 532 | + .buf_size = BUFFER_SAMPLES, |
michael@202 | 533 | + .plc_samples = 160, |
michael@202 | 534 | +}; |
michael@202 | 535 | + |
michael@202 | 536 | +static struct ast_translator lintog722 = { |
michael@202 | 537 | + .name = "lintog722", |
michael@202 | 538 | + .srcfmt = AST_FORMAT_SLINEAR, |
michael@202 | 539 | + .dstfmt = AST_FORMAT_G722, |
michael@202 | 540 | + .newpvt = lintog722_new, /* same for both directions */ |
michael@202 | 541 | + .framein = lintog722_framein, |
michael@202 | 542 | + .sample = lintog722_sample, |
michael@202 | 543 | + .desc_size = sizeof(struct g722_encoder_pvt), |
michael@202 | 544 | + .buffer_samples = BUFFER_SAMPLES * 2, |
michael@202 | 545 | + .buf_size = BUFFER_SAMPLES, |
michael@202 | 546 | +}; |
michael@202 | 547 | + |
michael@202 | 548 | +static struct ast_translator g722tolin16 = { |
michael@202 | 549 | + .name = "g722tolin16", |
michael@202 | 550 | + .srcfmt = AST_FORMAT_G722, |
michael@202 | 551 | + .dstfmt = AST_FORMAT_SLINEAR16, |
michael@202 | 552 | + .newpvt = g722tolin16_new, /* same for both directions */ |
michael@202 | 553 | + .framein = g722tolin_framein, |
michael@202 | 554 | + .sample = g722tolin16_sample, |
michael@202 | 555 | + .desc_size = sizeof(struct g722_decoder_pvt), |
michael@202 | 556 | + .buffer_samples = BUFFER_SAMPLES / sizeof(int16_t), |
michael@202 | 557 | + .buf_size = BUFFER_SAMPLES, |
michael@202 | 558 | + .plc_samples = 160, |
michael@202 | 559 | +}; |
michael@202 | 560 | + |
michael@202 | 561 | +static struct ast_translator lin16tog722 = { |
michael@202 | 562 | + .name = "lin16tog722", |
michael@202 | 563 | + .srcfmt = AST_FORMAT_SLINEAR16, |
michael@202 | 564 | + .dstfmt = AST_FORMAT_G722, |
michael@202 | 565 | + .newpvt = lin16tog722_new, /* same for both directions */ |
michael@202 | 566 | + .framein = lintog722_framein, |
michael@202 | 567 | + .sample = lin16tog722_sample, |
michael@202 | 568 | + .desc_size = sizeof(struct g722_encoder_pvt), |
michael@202 | 569 | + .buffer_samples = BUFFER_SAMPLES * 2, |
michael@202 | 570 | + .buf_size = BUFFER_SAMPLES, |
michael@202 | 571 | +}; |
michael@202 | 572 | + |
michael@202 | 573 | +static int parse_config(int reload) |
michael@202 | 574 | +{ |
michael@202 | 575 | + struct ast_variable *var; |
michael@202 | 576 | + struct ast_config *cfg = ast_config_load("codecs.conf"); |
michael@202 | 577 | + |
michael@202 | 578 | + if (cfg == NULL) |
michael@202 | 579 | + return 0; |
michael@202 | 580 | + if (cfg == CONFIG_STATUS_FILEUNCHANGED) |
michael@202 | 581 | + return 0; |
michael@202 | 582 | + for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { |
michael@202 | 583 | + if (!strcasecmp(var->name, "genericplc")) { |
michael@202 | 584 | + g722tolin.useplc = ast_true(var->value) ? 1 : 0; |
michael@202 | 585 | + if (option_verbose > 2) |
michael@202 | 586 | + ast_verbose(VERBOSE_PREFIX_3 "codec_g722: %susing generic PLC\n", |
michael@202 | 587 | + g722tolin.useplc ? "" : "not "); |
michael@202 | 588 | + } |
michael@202 | 589 | + } |
michael@202 | 590 | + ast_config_destroy(cfg); |
michael@202 | 591 | + return 0; |
michael@202 | 592 | +} |
michael@202 | 593 | + |
michael@202 | 594 | +static int reload(void) |
michael@202 | 595 | +{ |
michael@202 | 596 | + if (parse_config(1)) |
michael@202 | 597 | + return AST_MODULE_LOAD_DECLINE; |
michael@202 | 598 | + return AST_MODULE_LOAD_SUCCESS; |
michael@202 | 599 | +} |
michael@202 | 600 | + |
michael@202 | 601 | +static int unload_module(void) |
michael@202 | 602 | +{ |
michael@202 | 603 | + int res = 0; |
michael@202 | 604 | + |
michael@202 | 605 | + res |= ast_unregister_translator(&g722tolin); |
michael@202 | 606 | + res |= ast_unregister_translator(&lintog722); |
michael@202 | 607 | + res |= ast_unregister_translator(&g722tolin16); |
michael@202 | 608 | + res |= ast_unregister_translator(&lin16tog722); |
michael@202 | 609 | + |
michael@202 | 610 | + return res; |
michael@202 | 611 | +} |
michael@202 | 612 | + |
michael@202 | 613 | +static int load_module(void) |
michael@202 | 614 | +{ |
michael@202 | 615 | + int res = 0; |
michael@202 | 616 | + |
michael@202 | 617 | + if (parse_config(0)) |
michael@202 | 618 | + return AST_MODULE_LOAD_DECLINE; |
michael@202 | 619 | + |
michael@202 | 620 | + res |= ast_register_translator(&g722tolin); |
michael@202 | 621 | + res |= ast_register_translator(&lintog722); |
michael@202 | 622 | + res |= ast_register_translator(&g722tolin16); |
michael@202 | 623 | + res |= ast_register_translator(&lin16tog722); |
michael@202 | 624 | + |
michael@202 | 625 | + if (res) { |
michael@202 | 626 | + unload_module(); |
michael@202 | 627 | + return AST_MODULE_LOAD_FAILURE; |
michael@202 | 628 | + } |
michael@202 | 629 | + |
michael@202 | 630 | + return AST_MODULE_LOAD_SUCCESS; |
michael@202 | 631 | +} |
michael@202 | 632 | + |
michael@202 | 633 | +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.722-64kbps G722 Transcoder", |
michael@202 | 634 | + .load = load_module, |
michael@202 | 635 | + .unload = unload_module, |
michael@202 | 636 | + .reload = reload, |
michael@202 | 637 | + ); |
michael@202 | 638 | Index: codecs/g722/g722_decode.c |
michael@202 | 639 | diff -Nau codecs/g722/g722_decode.c.orig codecs/g722/g722_decode.c |
michael@202 | 640 | --- codecs/g722/g722_decode.c.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 641 | +++ codecs/g722/g722_decode.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 642 | @@ -0,0 +1,398 @@ |
michael@202 | 643 | +/* |
michael@202 | 644 | + * SpanDSP - a series of DSP components for telephony |
michael@202 | 645 | + * |
michael@202 | 646 | + * g722_decode.c - The ITU G.722 codec, decode part. |
michael@202 | 647 | + * |
michael@202 | 648 | + * Written by Steve Underwood <steveu@coppice.org> |
michael@202 | 649 | + * |
michael@202 | 650 | + * Copyright (C) 2005 Steve Underwood |
michael@202 | 651 | + * |
michael@202 | 652 | + * Despite my general liking of the GPL, I place my own contributions |
michael@202 | 653 | + * to this code in the public domain for the benefit of all mankind - |
michael@202 | 654 | + * even the slimy ones who might try to proprietize my work and use it |
michael@202 | 655 | + * to my detriment. |
michael@202 | 656 | + * |
michael@202 | 657 | + * Based in part on a single channel G.722 codec which is: |
michael@202 | 658 | + * |
michael@202 | 659 | + * Copyright (c) CMU 1993 |
michael@202 | 660 | + * Computer Science, Speech Group |
michael@202 | 661 | + * Chengxiang Lu and Alex Hauptmann |
michael@202 | 662 | + * |
michael@202 | 663 | + * $Id: g722_decode.c 48661 2006-12-21 00:08:21Z mattf $ |
michael@202 | 664 | + */ |
michael@202 | 665 | + |
michael@202 | 666 | +/*! \file */ |
michael@202 | 667 | + |
michael@202 | 668 | +#ifdef HAVE_CONFIG_H |
michael@202 | 669 | +#include <config.h> |
michael@202 | 670 | +#endif |
michael@202 | 671 | + |
michael@202 | 672 | +#include <stdio.h> |
michael@202 | 673 | +#include <inttypes.h> |
michael@202 | 674 | +#include <memory.h> |
michael@202 | 675 | +#include <stdlib.h> |
michael@202 | 676 | +#if 0 |
michael@202 | 677 | +#include <tgmath.h> |
michael@202 | 678 | +#endif |
michael@202 | 679 | + |
michael@202 | 680 | +#include "g722.h" |
michael@202 | 681 | + |
michael@202 | 682 | +#if !defined(FALSE) |
michael@202 | 683 | +#define FALSE 0 |
michael@202 | 684 | +#endif |
michael@202 | 685 | +#if !defined(TRUE) |
michael@202 | 686 | +#define TRUE (!FALSE) |
michael@202 | 687 | +#endif |
michael@202 | 688 | + |
michael@202 | 689 | +static __inline__ int16_t saturate(int32_t amp) |
michael@202 | 690 | +{ |
michael@202 | 691 | + int16_t amp16; |
michael@202 | 692 | + |
michael@202 | 693 | + /* Hopefully this is optimised for the common case - not clipping */ |
michael@202 | 694 | + amp16 = (int16_t) amp; |
michael@202 | 695 | + if (amp == amp16) |
michael@202 | 696 | + return amp16; |
michael@202 | 697 | + if (amp > INT16_MAX) |
michael@202 | 698 | + return INT16_MAX; |
michael@202 | 699 | + return INT16_MIN; |
michael@202 | 700 | +} |
michael@202 | 701 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 702 | + |
michael@202 | 703 | +static void block4(g722_decode_state_t *s, int band, int d); |
michael@202 | 704 | + |
michael@202 | 705 | +static void block4(g722_decode_state_t *s, int band, int d) |
michael@202 | 706 | +{ |
michael@202 | 707 | + int wd1; |
michael@202 | 708 | + int wd2; |
michael@202 | 709 | + int wd3; |
michael@202 | 710 | + int i; |
michael@202 | 711 | + |
michael@202 | 712 | + /* Block 4, RECONS */ |
michael@202 | 713 | + s->band[band].d[0] = d; |
michael@202 | 714 | + s->band[band].r[0] = saturate(s->band[band].s + d); |
michael@202 | 715 | + |
michael@202 | 716 | + /* Block 4, PARREC */ |
michael@202 | 717 | + s->band[band].p[0] = saturate(s->band[band].sz + d); |
michael@202 | 718 | + |
michael@202 | 719 | + /* Block 4, UPPOL2 */ |
michael@202 | 720 | + for (i = 0; i < 3; i++) |
michael@202 | 721 | + s->band[band].sg[i] = s->band[band].p[i] >> 15; |
michael@202 | 722 | + wd1 = saturate(s->band[band].a[1] << 2); |
michael@202 | 723 | + |
michael@202 | 724 | + wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1; |
michael@202 | 725 | + if (wd2 > 32767) |
michael@202 | 726 | + wd2 = 32767; |
michael@202 | 727 | + wd3 = (s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128; |
michael@202 | 728 | + wd3 += (wd2 >> 7); |
michael@202 | 729 | + wd3 += (s->band[band].a[2]*32512) >> 15; |
michael@202 | 730 | + if (wd3 > 12288) |
michael@202 | 731 | + wd3 = 12288; |
michael@202 | 732 | + else if (wd3 < -12288) |
michael@202 | 733 | + wd3 = -12288; |
michael@202 | 734 | + s->band[band].ap[2] = wd3; |
michael@202 | 735 | + |
michael@202 | 736 | + /* Block 4, UPPOL1 */ |
michael@202 | 737 | + s->band[band].sg[0] = s->band[band].p[0] >> 15; |
michael@202 | 738 | + s->band[band].sg[1] = s->band[band].p[1] >> 15; |
michael@202 | 739 | + wd1 = (s->band[band].sg[0] == s->band[band].sg[1]) ? 192 : -192; |
michael@202 | 740 | + wd2 = (s->band[band].a[1]*32640) >> 15; |
michael@202 | 741 | + |
michael@202 | 742 | + s->band[band].ap[1] = saturate(wd1 + wd2); |
michael@202 | 743 | + wd3 = saturate(15360 - s->band[band].ap[2]); |
michael@202 | 744 | + if (s->band[band].ap[1] > wd3) |
michael@202 | 745 | + s->band[band].ap[1] = wd3; |
michael@202 | 746 | + else if (s->band[band].ap[1] < -wd3) |
michael@202 | 747 | + s->band[band].ap[1] = -wd3; |
michael@202 | 748 | + |
michael@202 | 749 | + /* Block 4, UPZERO */ |
michael@202 | 750 | + wd1 = (d == 0) ? 0 : 128; |
michael@202 | 751 | + s->band[band].sg[0] = d >> 15; |
michael@202 | 752 | + for (i = 1; i < 7; i++) |
michael@202 | 753 | + { |
michael@202 | 754 | + s->band[band].sg[i] = s->band[band].d[i] >> 15; |
michael@202 | 755 | + wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1; |
michael@202 | 756 | + wd3 = (s->band[band].b[i]*32640) >> 15; |
michael@202 | 757 | + s->band[band].bp[i] = saturate(wd2 + wd3); |
michael@202 | 758 | + } |
michael@202 | 759 | + |
michael@202 | 760 | + /* Block 4, DELAYA */ |
michael@202 | 761 | + for (i = 6; i > 0; i--) |
michael@202 | 762 | + { |
michael@202 | 763 | + s->band[band].d[i] = s->band[band].d[i - 1]; |
michael@202 | 764 | + s->band[band].b[i] = s->band[band].bp[i]; |
michael@202 | 765 | + } |
michael@202 | 766 | + |
michael@202 | 767 | + for (i = 2; i > 0; i--) |
michael@202 | 768 | + { |
michael@202 | 769 | + s->band[band].r[i] = s->band[band].r[i - 1]; |
michael@202 | 770 | + s->band[band].p[i] = s->band[band].p[i - 1]; |
michael@202 | 771 | + s->band[band].a[i] = s->band[band].ap[i]; |
michael@202 | 772 | + } |
michael@202 | 773 | + |
michael@202 | 774 | + /* Block 4, FILTEP */ |
michael@202 | 775 | + wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]); |
michael@202 | 776 | + wd1 = (s->band[band].a[1]*wd1) >> 15; |
michael@202 | 777 | + wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]); |
michael@202 | 778 | + wd2 = (s->band[band].a[2]*wd2) >> 15; |
michael@202 | 779 | + s->band[band].sp = saturate(wd1 + wd2); |
michael@202 | 780 | + |
michael@202 | 781 | + /* Block 4, FILTEZ */ |
michael@202 | 782 | + s->band[band].sz = 0; |
michael@202 | 783 | + for (i = 6; i > 0; i--) |
michael@202 | 784 | + { |
michael@202 | 785 | + wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]); |
michael@202 | 786 | + s->band[band].sz += (s->band[band].b[i]*wd1) >> 15; |
michael@202 | 787 | + } |
michael@202 | 788 | + s->band[band].sz = saturate(s->band[band].sz); |
michael@202 | 789 | + |
michael@202 | 790 | + /* Block 4, PREDIC */ |
michael@202 | 791 | + s->band[band].s = saturate(s->band[band].sp + s->band[band].sz); |
michael@202 | 792 | +} |
michael@202 | 793 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 794 | + |
michael@202 | 795 | +g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options) |
michael@202 | 796 | +{ |
michael@202 | 797 | + if (s == NULL) |
michael@202 | 798 | + { |
michael@202 | 799 | + if ((s = (g722_decode_state_t *) malloc(sizeof(*s))) == NULL) |
michael@202 | 800 | + return NULL; |
michael@202 | 801 | + } |
michael@202 | 802 | + memset(s, 0, sizeof(*s)); |
michael@202 | 803 | + if (rate == 48000) |
michael@202 | 804 | + s->bits_per_sample = 6; |
michael@202 | 805 | + else if (rate == 56000) |
michael@202 | 806 | + s->bits_per_sample = 7; |
michael@202 | 807 | + else |
michael@202 | 808 | + s->bits_per_sample = 8; |
michael@202 | 809 | + if ((options & G722_SAMPLE_RATE_8000)) |
michael@202 | 810 | + s->eight_k = TRUE; |
michael@202 | 811 | + if ((options & G722_PACKED) && s->bits_per_sample != 8) |
michael@202 | 812 | + s->packed = TRUE; |
michael@202 | 813 | + else |
michael@202 | 814 | + s->packed = FALSE; |
michael@202 | 815 | + s->band[0].det = 32; |
michael@202 | 816 | + s->band[1].det = 8; |
michael@202 | 817 | + return s; |
michael@202 | 818 | +} |
michael@202 | 819 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 820 | + |
michael@202 | 821 | +int g722_decode_release(g722_decode_state_t *s) |
michael@202 | 822 | +{ |
michael@202 | 823 | + free(s); |
michael@202 | 824 | + return 0; |
michael@202 | 825 | +} |
michael@202 | 826 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 827 | + |
michael@202 | 828 | +int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len) |
michael@202 | 829 | +{ |
michael@202 | 830 | + static const int wl[8] = {-60, -30, 58, 172, 334, 538, 1198, 3042 }; |
michael@202 | 831 | + static const int rl42[16] = {0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 }; |
michael@202 | 832 | + static const int ilb[32] = |
michael@202 | 833 | + { |
michael@202 | 834 | + 2048, 2093, 2139, 2186, 2233, 2282, 2332, |
michael@202 | 835 | + 2383, 2435, 2489, 2543, 2599, 2656, 2714, |
michael@202 | 836 | + 2774, 2834, 2896, 2960, 3025, 3091, 3158, |
michael@202 | 837 | + 3228, 3298, 3371, 3444, 3520, 3597, 3676, |
michael@202 | 838 | + 3756, 3838, 3922, 4008 |
michael@202 | 839 | + }; |
michael@202 | 840 | + static const int wh[3] = {0, -214, 798}; |
michael@202 | 841 | + static const int rh2[4] = {2, 1, 2, 1}; |
michael@202 | 842 | + static const int qm2[4] = {-7408, -1616, 7408, 1616}; |
michael@202 | 843 | + static const int qm4[16] = |
michael@202 | 844 | + { |
michael@202 | 845 | + 0, -20456, -12896, -8968, |
michael@202 | 846 | + -6288, -4240, -2584, -1200, |
michael@202 | 847 | + 20456, 12896, 8968, 6288, |
michael@202 | 848 | + 4240, 2584, 1200, 0 |
michael@202 | 849 | + }; |
michael@202 | 850 | + static const int qm5[32] = |
michael@202 | 851 | + { |
michael@202 | 852 | + -280, -280, -23352, -17560, |
michael@202 | 853 | + -14120, -11664, -9752, -8184, |
michael@202 | 854 | + -6864, -5712, -4696, -3784, |
michael@202 | 855 | + -2960, -2208, -1520, -880, |
michael@202 | 856 | + 23352, 17560, 14120, 11664, |
michael@202 | 857 | + 9752, 8184, 6864, 5712, |
michael@202 | 858 | + 4696, 3784, 2960, 2208, |
michael@202 | 859 | + 1520, 880, 280, -280 |
michael@202 | 860 | + }; |
michael@202 | 861 | + static const int qm6[64] = |
michael@202 | 862 | + { |
michael@202 | 863 | + -136, -136, -136, -136, |
michael@202 | 864 | + -24808, -21904, -19008, -16704, |
michael@202 | 865 | + -14984, -13512, -12280, -11192, |
michael@202 | 866 | + -10232, -9360, -8576, -7856, |
michael@202 | 867 | + -7192, -6576, -6000, -5456, |
michael@202 | 868 | + -4944, -4464, -4008, -3576, |
michael@202 | 869 | + -3168, -2776, -2400, -2032, |
michael@202 | 870 | + -1688, -1360, -1040, -728, |
michael@202 | 871 | + 24808, 21904, 19008, 16704, |
michael@202 | 872 | + 14984, 13512, 12280, 11192, |
michael@202 | 873 | + 10232, 9360, 8576, 7856, |
michael@202 | 874 | + 7192, 6576, 6000, 5456, |
michael@202 | 875 | + 4944, 4464, 4008, 3576, |
michael@202 | 876 | + 3168, 2776, 2400, 2032, |
michael@202 | 877 | + 1688, 1360, 1040, 728, |
michael@202 | 878 | + 432, 136, -432, -136 |
michael@202 | 879 | + }; |
michael@202 | 880 | + static const int qmf_coeffs[12] = |
michael@202 | 881 | + { |
michael@202 | 882 | + 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11, |
michael@202 | 883 | + }; |
michael@202 | 884 | + |
michael@202 | 885 | + int dlowt; |
michael@202 | 886 | + int rlow; |
michael@202 | 887 | + int ihigh; |
michael@202 | 888 | + int dhigh; |
michael@202 | 889 | + int rhigh; |
michael@202 | 890 | + int xout1; |
michael@202 | 891 | + int xout2; |
michael@202 | 892 | + int wd1; |
michael@202 | 893 | + int wd2; |
michael@202 | 894 | + int wd3; |
michael@202 | 895 | + int code; |
michael@202 | 896 | + int outlen; |
michael@202 | 897 | + int i; |
michael@202 | 898 | + int j; |
michael@202 | 899 | + |
michael@202 | 900 | + outlen = 0; |
michael@202 | 901 | + rhigh = 0; |
michael@202 | 902 | + for (j = 0; j < len; ) |
michael@202 | 903 | + { |
michael@202 | 904 | + if (s->packed) |
michael@202 | 905 | + { |
michael@202 | 906 | + /* Unpack the code bits */ |
michael@202 | 907 | + if (s->in_bits < s->bits_per_sample) |
michael@202 | 908 | + { |
michael@202 | 909 | + s->in_buffer |= (g722_data[j++] << s->in_bits); |
michael@202 | 910 | + s->in_bits += 8; |
michael@202 | 911 | + } |
michael@202 | 912 | + code = s->in_buffer & ((1 << s->bits_per_sample) - 1); |
michael@202 | 913 | + s->in_buffer >>= s->bits_per_sample; |
michael@202 | 914 | + s->in_bits -= s->bits_per_sample; |
michael@202 | 915 | + } |
michael@202 | 916 | + else |
michael@202 | 917 | + { |
michael@202 | 918 | + code = g722_data[j++]; |
michael@202 | 919 | + } |
michael@202 | 920 | + |
michael@202 | 921 | + switch (s->bits_per_sample) |
michael@202 | 922 | + { |
michael@202 | 923 | + default: |
michael@202 | 924 | + case 8: |
michael@202 | 925 | + wd1 = code & 0x3F; |
michael@202 | 926 | + ihigh = (code >> 6) & 0x03; |
michael@202 | 927 | + wd2 = qm6[wd1]; |
michael@202 | 928 | + wd1 >>= 2; |
michael@202 | 929 | + break; |
michael@202 | 930 | + case 7: |
michael@202 | 931 | + wd1 = code & 0x1F; |
michael@202 | 932 | + ihigh = (code >> 5) & 0x03; |
michael@202 | 933 | + wd2 = qm5[wd1]; |
michael@202 | 934 | + wd1 >>= 1; |
michael@202 | 935 | + break; |
michael@202 | 936 | + case 6: |
michael@202 | 937 | + wd1 = code & 0x0F; |
michael@202 | 938 | + ihigh = (code >> 4) & 0x03; |
michael@202 | 939 | + wd2 = qm4[wd1]; |
michael@202 | 940 | + break; |
michael@202 | 941 | + } |
michael@202 | 942 | + /* Block 5L, LOW BAND INVQBL */ |
michael@202 | 943 | + wd2 = (s->band[0].det*wd2) >> 15; |
michael@202 | 944 | + /* Block 5L, RECONS */ |
michael@202 | 945 | + rlow = s->band[0].s + wd2; |
michael@202 | 946 | + /* Block 6L, LIMIT */ |
michael@202 | 947 | + if (rlow > 16383) |
michael@202 | 948 | + rlow = 16383; |
michael@202 | 949 | + else if (rlow < -16384) |
michael@202 | 950 | + rlow = -16384; |
michael@202 | 951 | + |
michael@202 | 952 | + /* Block 2L, INVQAL */ |
michael@202 | 953 | + wd2 = qm4[wd1]; |
michael@202 | 954 | + dlowt = (s->band[0].det*wd2) >> 15; |
michael@202 | 955 | + |
michael@202 | 956 | + /* Block 3L, LOGSCL */ |
michael@202 | 957 | + wd2 = rl42[wd1]; |
michael@202 | 958 | + wd1 = (s->band[0].nb*127) >> 7; |
michael@202 | 959 | + wd1 += wl[wd2]; |
michael@202 | 960 | + if (wd1 < 0) |
michael@202 | 961 | + wd1 = 0; |
michael@202 | 962 | + else if (wd1 > 18432) |
michael@202 | 963 | + wd1 = 18432; |
michael@202 | 964 | + s->band[0].nb = wd1; |
michael@202 | 965 | + |
michael@202 | 966 | + /* Block 3L, SCALEL */ |
michael@202 | 967 | + wd1 = (s->band[0].nb >> 6) & 31; |
michael@202 | 968 | + wd2 = 8 - (s->band[0].nb >> 11); |
michael@202 | 969 | + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); |
michael@202 | 970 | + s->band[0].det = wd3 << 2; |
michael@202 | 971 | + |
michael@202 | 972 | + block4(s, 0, dlowt); |
michael@202 | 973 | + |
michael@202 | 974 | + if (!s->eight_k) |
michael@202 | 975 | + { |
michael@202 | 976 | + /* Block 2H, INVQAH */ |
michael@202 | 977 | + wd2 = qm2[ihigh]; |
michael@202 | 978 | + dhigh = (s->band[1].det*wd2) >> 15; |
michael@202 | 979 | + /* Block 5H, RECONS */ |
michael@202 | 980 | + rhigh = dhigh + s->band[1].s; |
michael@202 | 981 | + /* Block 6H, LIMIT */ |
michael@202 | 982 | + if (rhigh > 16383) |
michael@202 | 983 | + rhigh = 16383; |
michael@202 | 984 | + else if (rhigh < -16384) |
michael@202 | 985 | + rhigh = -16384; |
michael@202 | 986 | + |
michael@202 | 987 | + /* Block 2H, INVQAH */ |
michael@202 | 988 | + wd2 = rh2[ihigh]; |
michael@202 | 989 | + wd1 = (s->band[1].nb*127) >> 7; |
michael@202 | 990 | + wd1 += wh[wd2]; |
michael@202 | 991 | + if (wd1 < 0) |
michael@202 | 992 | + wd1 = 0; |
michael@202 | 993 | + else if (wd1 > 22528) |
michael@202 | 994 | + wd1 = 22528; |
michael@202 | 995 | + s->band[1].nb = wd1; |
michael@202 | 996 | + |
michael@202 | 997 | + /* Block 3H, SCALEH */ |
michael@202 | 998 | + wd1 = (s->band[1].nb >> 6) & 31; |
michael@202 | 999 | + wd2 = 10 - (s->band[1].nb >> 11); |
michael@202 | 1000 | + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); |
michael@202 | 1001 | + s->band[1].det = wd3 << 2; |
michael@202 | 1002 | + |
michael@202 | 1003 | + block4(s, 1, dhigh); |
michael@202 | 1004 | + } |
michael@202 | 1005 | + |
michael@202 | 1006 | + if (s->itu_test_mode) |
michael@202 | 1007 | + { |
michael@202 | 1008 | + amp[outlen++] = (int16_t) (rlow << 1); |
michael@202 | 1009 | + amp[outlen++] = (int16_t) (rhigh << 1); |
michael@202 | 1010 | + } |
michael@202 | 1011 | + else |
michael@202 | 1012 | + { |
michael@202 | 1013 | + if (s->eight_k) |
michael@202 | 1014 | + { |
michael@202 | 1015 | + amp[outlen++] = (int16_t) rlow; |
michael@202 | 1016 | + } |
michael@202 | 1017 | + else |
michael@202 | 1018 | + { |
michael@202 | 1019 | + /* Apply the receive QMF */ |
michael@202 | 1020 | + for (i = 0; i < 22; i++) |
michael@202 | 1021 | + s->x[i] = s->x[i + 2]; |
michael@202 | 1022 | + s->x[22] = rlow + rhigh; |
michael@202 | 1023 | + s->x[23] = rlow - rhigh; |
michael@202 | 1024 | + |
michael@202 | 1025 | + xout1 = 0; |
michael@202 | 1026 | + xout2 = 0; |
michael@202 | 1027 | + for (i = 0; i < 12; i++) |
michael@202 | 1028 | + { |
michael@202 | 1029 | + xout2 += s->x[2*i]*qmf_coeffs[i]; |
michael@202 | 1030 | + xout1 += s->x[2*i + 1]*qmf_coeffs[11 - i]; |
michael@202 | 1031 | + } |
michael@202 | 1032 | + amp[outlen++] = (int16_t) (xout1 >> 12); |
michael@202 | 1033 | + amp[outlen++] = (int16_t) (xout2 >> 12); |
michael@202 | 1034 | + } |
michael@202 | 1035 | + } |
michael@202 | 1036 | + } |
michael@202 | 1037 | + return outlen; |
michael@202 | 1038 | +} |
michael@202 | 1039 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 1040 | +/*- End of file ------------------------------------------------------------*/ |
michael@202 | 1041 | Index: codecs/g722/g722_encode.c |
michael@202 | 1042 | diff -Nau codecs/g722/g722_encode.c.orig codecs/g722/g722_encode.c |
michael@202 | 1043 | --- codecs/g722/g722_encode.c.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 1044 | +++ codecs/g722/g722_encode.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1045 | @@ -0,0 +1,400 @@ |
michael@202 | 1046 | +/* |
michael@202 | 1047 | + * SpanDSP - a series of DSP components for telephony |
michael@202 | 1048 | + * |
michael@202 | 1049 | + * g722_encode.c - The ITU G.722 codec, encode part. |
michael@202 | 1050 | + * |
michael@202 | 1051 | + * Written by Steve Underwood <steveu@coppice.org> |
michael@202 | 1052 | + * |
michael@202 | 1053 | + * Copyright (C) 2005 Steve Underwood |
michael@202 | 1054 | + * |
michael@202 | 1055 | + * All rights reserved. |
michael@202 | 1056 | + * |
michael@202 | 1057 | + * Despite my general liking of the GPL, I place my own contributions |
michael@202 | 1058 | + * to this code in the public domain for the benefit of all mankind - |
michael@202 | 1059 | + * even the slimy ones who might try to proprietize my work and use it |
michael@202 | 1060 | + * to my detriment. |
michael@202 | 1061 | + * |
michael@202 | 1062 | + * Based on a single channel 64kbps only G.722 codec which is: |
michael@202 | 1063 | + * |
michael@202 | 1064 | + ***** Copyright (c) CMU 1993 ***** |
michael@202 | 1065 | + * Computer Science, Speech Group |
michael@202 | 1066 | + * Chengxiang Lu and Alex Hauptmann |
michael@202 | 1067 | + * |
michael@202 | 1068 | + * $Id: g722_encode.c 48661 2006-12-21 00:08:21Z mattf $ |
michael@202 | 1069 | + */ |
michael@202 | 1070 | + |
michael@202 | 1071 | +/*! \file */ |
michael@202 | 1072 | + |
michael@202 | 1073 | +#ifdef HAVE_CONFIG_H |
michael@202 | 1074 | +#include <config.h> |
michael@202 | 1075 | +#endif |
michael@202 | 1076 | + |
michael@202 | 1077 | +#include <stdio.h> |
michael@202 | 1078 | +#include <inttypes.h> |
michael@202 | 1079 | +#include <memory.h> |
michael@202 | 1080 | +#include <stdlib.h> |
michael@202 | 1081 | +#if 0 |
michael@202 | 1082 | +#include <tgmath.h> |
michael@202 | 1083 | +#endif |
michael@202 | 1084 | + |
michael@202 | 1085 | +#include "g722.h" |
michael@202 | 1086 | + |
michael@202 | 1087 | +#if !defined(FALSE) |
michael@202 | 1088 | +#define FALSE 0 |
michael@202 | 1089 | +#endif |
michael@202 | 1090 | +#if !defined(TRUE) |
michael@202 | 1091 | +#define TRUE (!FALSE) |
michael@202 | 1092 | +#endif |
michael@202 | 1093 | + |
michael@202 | 1094 | +static __inline__ int16_t saturate(int32_t amp) |
michael@202 | 1095 | +{ |
michael@202 | 1096 | + int16_t amp16; |
michael@202 | 1097 | + |
michael@202 | 1098 | + /* Hopefully this is optimised for the common case - not clipping */ |
michael@202 | 1099 | + amp16 = (int16_t) amp; |
michael@202 | 1100 | + if (amp == amp16) |
michael@202 | 1101 | + return amp16; |
michael@202 | 1102 | + if (amp > INT16_MAX) |
michael@202 | 1103 | + return INT16_MAX; |
michael@202 | 1104 | + return INT16_MIN; |
michael@202 | 1105 | +} |
michael@202 | 1106 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 1107 | + |
michael@202 | 1108 | +static void block4(g722_encode_state_t *s, int band, int d) |
michael@202 | 1109 | +{ |
michael@202 | 1110 | + int wd1; |
michael@202 | 1111 | + int wd2; |
michael@202 | 1112 | + int wd3; |
michael@202 | 1113 | + int i; |
michael@202 | 1114 | + |
michael@202 | 1115 | + /* Block 4, RECONS */ |
michael@202 | 1116 | + s->band[band].d[0] = d; |
michael@202 | 1117 | + s->band[band].r[0] = saturate(s->band[band].s + d); |
michael@202 | 1118 | + |
michael@202 | 1119 | + /* Block 4, PARREC */ |
michael@202 | 1120 | + s->band[band].p[0] = saturate(s->band[band].sz + d); |
michael@202 | 1121 | + |
michael@202 | 1122 | + /* Block 4, UPPOL2 */ |
michael@202 | 1123 | + for (i = 0; i < 3; i++) |
michael@202 | 1124 | + s->band[band].sg[i] = s->band[band].p[i] >> 15; |
michael@202 | 1125 | + wd1 = saturate(s->band[band].a[1] << 2); |
michael@202 | 1126 | + |
michael@202 | 1127 | + wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1; |
michael@202 | 1128 | + if (wd2 > 32767) |
michael@202 | 1129 | + wd2 = 32767; |
michael@202 | 1130 | + wd3 = (wd2 >> 7) + ((s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128); |
michael@202 | 1131 | + wd3 += (s->band[band].a[2]*32512) >> 15; |
michael@202 | 1132 | + if (wd3 > 12288) |
michael@202 | 1133 | + wd3 = 12288; |
michael@202 | 1134 | + else if (wd3 < -12288) |
michael@202 | 1135 | + wd3 = -12288; |
michael@202 | 1136 | + s->band[band].ap[2] = wd3; |
michael@202 | 1137 | + |
michael@202 | 1138 | + /* Block 4, UPPOL1 */ |
michael@202 | 1139 | + s->band[band].sg[0] = s->band[band].p[0] >> 15; |
michael@202 | 1140 | + s->band[band].sg[1] = s->band[band].p[1] >> 15; |
michael@202 | 1141 | + wd1 = (s->band[band].sg[0] == s->band[band].sg[1]) ? 192 : -192; |
michael@202 | 1142 | + wd2 = (s->band[band].a[1]*32640) >> 15; |
michael@202 | 1143 | + |
michael@202 | 1144 | + s->band[band].ap[1] = saturate(wd1 + wd2); |
michael@202 | 1145 | + wd3 = saturate(15360 - s->band[band].ap[2]); |
michael@202 | 1146 | + if (s->band[band].ap[1] > wd3) |
michael@202 | 1147 | + s->band[band].ap[1] = wd3; |
michael@202 | 1148 | + else if (s->band[band].ap[1] < -wd3) |
michael@202 | 1149 | + s->band[band].ap[1] = -wd3; |
michael@202 | 1150 | + |
michael@202 | 1151 | + /* Block 4, UPZERO */ |
michael@202 | 1152 | + wd1 = (d == 0) ? 0 : 128; |
michael@202 | 1153 | + s->band[band].sg[0] = d >> 15; |
michael@202 | 1154 | + for (i = 1; i < 7; i++) |
michael@202 | 1155 | + { |
michael@202 | 1156 | + s->band[band].sg[i] = s->band[band].d[i] >> 15; |
michael@202 | 1157 | + wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1; |
michael@202 | 1158 | + wd3 = (s->band[band].b[i]*32640) >> 15; |
michael@202 | 1159 | + s->band[band].bp[i] = saturate(wd2 + wd3); |
michael@202 | 1160 | + } |
michael@202 | 1161 | + |
michael@202 | 1162 | + /* Block 4, DELAYA */ |
michael@202 | 1163 | + for (i = 6; i > 0; i--) |
michael@202 | 1164 | + { |
michael@202 | 1165 | + s->band[band].d[i] = s->band[band].d[i - 1]; |
michael@202 | 1166 | + s->band[band].b[i] = s->band[band].bp[i]; |
michael@202 | 1167 | + } |
michael@202 | 1168 | + |
michael@202 | 1169 | + for (i = 2; i > 0; i--) |
michael@202 | 1170 | + { |
michael@202 | 1171 | + s->band[band].r[i] = s->band[band].r[i - 1]; |
michael@202 | 1172 | + s->band[band].p[i] = s->band[band].p[i - 1]; |
michael@202 | 1173 | + s->band[band].a[i] = s->band[band].ap[i]; |
michael@202 | 1174 | + } |
michael@202 | 1175 | + |
michael@202 | 1176 | + /* Block 4, FILTEP */ |
michael@202 | 1177 | + wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]); |
michael@202 | 1178 | + wd1 = (s->band[band].a[1]*wd1) >> 15; |
michael@202 | 1179 | + wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]); |
michael@202 | 1180 | + wd2 = (s->band[band].a[2]*wd2) >> 15; |
michael@202 | 1181 | + s->band[band].sp = saturate(wd1 + wd2); |
michael@202 | 1182 | + |
michael@202 | 1183 | + /* Block 4, FILTEZ */ |
michael@202 | 1184 | + s->band[band].sz = 0; |
michael@202 | 1185 | + for (i = 6; i > 0; i--) |
michael@202 | 1186 | + { |
michael@202 | 1187 | + wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]); |
michael@202 | 1188 | + s->band[band].sz += (s->band[band].b[i]*wd1) >> 15; |
michael@202 | 1189 | + } |
michael@202 | 1190 | + s->band[band].sz = saturate(s->band[band].sz); |
michael@202 | 1191 | + |
michael@202 | 1192 | + /* Block 4, PREDIC */ |
michael@202 | 1193 | + s->band[band].s = saturate(s->band[band].sp + s->band[band].sz); |
michael@202 | 1194 | +} |
michael@202 | 1195 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 1196 | + |
michael@202 | 1197 | +g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options) |
michael@202 | 1198 | +{ |
michael@202 | 1199 | + if (s == NULL) |
michael@202 | 1200 | + { |
michael@202 | 1201 | + if ((s = (g722_encode_state_t *) malloc(sizeof(*s))) == NULL) |
michael@202 | 1202 | + return NULL; |
michael@202 | 1203 | + } |
michael@202 | 1204 | + memset(s, 0, sizeof(*s)); |
michael@202 | 1205 | + if (rate == 48000) |
michael@202 | 1206 | + s->bits_per_sample = 6; |
michael@202 | 1207 | + else if (rate == 56000) |
michael@202 | 1208 | + s->bits_per_sample = 7; |
michael@202 | 1209 | + else |
michael@202 | 1210 | + s->bits_per_sample = 8; |
michael@202 | 1211 | + if ((options & G722_SAMPLE_RATE_8000)) |
michael@202 | 1212 | + s->eight_k = TRUE; |
michael@202 | 1213 | + if ((options & G722_PACKED) && s->bits_per_sample != 8) |
michael@202 | 1214 | + s->packed = TRUE; |
michael@202 | 1215 | + else |
michael@202 | 1216 | + s->packed = FALSE; |
michael@202 | 1217 | + s->band[0].det = 32; |
michael@202 | 1218 | + s->band[1].det = 8; |
michael@202 | 1219 | + return s; |
michael@202 | 1220 | +} |
michael@202 | 1221 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 1222 | + |
michael@202 | 1223 | +int g722_encode_release(g722_encode_state_t *s) |
michael@202 | 1224 | +{ |
michael@202 | 1225 | + free(s); |
michael@202 | 1226 | + return 0; |
michael@202 | 1227 | +} |
michael@202 | 1228 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 1229 | + |
michael@202 | 1230 | +int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len) |
michael@202 | 1231 | +{ |
michael@202 | 1232 | + static const int q6[32] = |
michael@202 | 1233 | + { |
michael@202 | 1234 | + 0, 35, 72, 110, 150, 190, 233, 276, |
michael@202 | 1235 | + 323, 370, 422, 473, 530, 587, 650, 714, |
michael@202 | 1236 | + 786, 858, 940, 1023, 1121, 1219, 1339, 1458, |
michael@202 | 1237 | + 1612, 1765, 1980, 2195, 2557, 2919, 0, 0 |
michael@202 | 1238 | + }; |
michael@202 | 1239 | + static const int iln[32] = |
michael@202 | 1240 | + { |
michael@202 | 1241 | + 0, 63, 62, 31, 30, 29, 28, 27, |
michael@202 | 1242 | + 26, 25, 24, 23, 22, 21, 20, 19, |
michael@202 | 1243 | + 18, 17, 16, 15, 14, 13, 12, 11, |
michael@202 | 1244 | + 10, 9, 8, 7, 6, 5, 4, 0 |
michael@202 | 1245 | + }; |
michael@202 | 1246 | + static const int ilp[32] = |
michael@202 | 1247 | + { |
michael@202 | 1248 | + 0, 61, 60, 59, 58, 57, 56, 55, |
michael@202 | 1249 | + 54, 53, 52, 51, 50, 49, 48, 47, |
michael@202 | 1250 | + 46, 45, 44, 43, 42, 41, 40, 39, |
michael@202 | 1251 | + 38, 37, 36, 35, 34, 33, 32, 0 |
michael@202 | 1252 | + }; |
michael@202 | 1253 | + static const int wl[8] = |
michael@202 | 1254 | + { |
michael@202 | 1255 | + -60, -30, 58, 172, 334, 538, 1198, 3042 |
michael@202 | 1256 | + }; |
michael@202 | 1257 | + static const int rl42[16] = |
michael@202 | 1258 | + { |
michael@202 | 1259 | + 0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 |
michael@202 | 1260 | + }; |
michael@202 | 1261 | + static const int ilb[32] = |
michael@202 | 1262 | + { |
michael@202 | 1263 | + 2048, 2093, 2139, 2186, 2233, 2282, 2332, |
michael@202 | 1264 | + 2383, 2435, 2489, 2543, 2599, 2656, 2714, |
michael@202 | 1265 | + 2774, 2834, 2896, 2960, 3025, 3091, 3158, |
michael@202 | 1266 | + 3228, 3298, 3371, 3444, 3520, 3597, 3676, |
michael@202 | 1267 | + 3756, 3838, 3922, 4008 |
michael@202 | 1268 | + }; |
michael@202 | 1269 | + static const int qm4[16] = |
michael@202 | 1270 | + { |
michael@202 | 1271 | + 0, -20456, -12896, -8968, |
michael@202 | 1272 | + -6288, -4240, -2584, -1200, |
michael@202 | 1273 | + 20456, 12896, 8968, 6288, |
michael@202 | 1274 | + 4240, 2584, 1200, 0 |
michael@202 | 1275 | + }; |
michael@202 | 1276 | + static const int qm2[4] = |
michael@202 | 1277 | + { |
michael@202 | 1278 | + -7408, -1616, 7408, 1616 |
michael@202 | 1279 | + }; |
michael@202 | 1280 | + static const int qmf_coeffs[12] = |
michael@202 | 1281 | + { |
michael@202 | 1282 | + 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11, |
michael@202 | 1283 | + }; |
michael@202 | 1284 | + static const int ihn[3] = {0, 1, 0}; |
michael@202 | 1285 | + static const int ihp[3] = {0, 3, 2}; |
michael@202 | 1286 | + static const int wh[3] = {0, -214, 798}; |
michael@202 | 1287 | + static const int rh2[4] = {2, 1, 2, 1}; |
michael@202 | 1288 | + |
michael@202 | 1289 | + int dlow; |
michael@202 | 1290 | + int dhigh; |
michael@202 | 1291 | + int el; |
michael@202 | 1292 | + int wd; |
michael@202 | 1293 | + int wd1; |
michael@202 | 1294 | + int ril; |
michael@202 | 1295 | + int wd2; |
michael@202 | 1296 | + int il4; |
michael@202 | 1297 | + int ih2; |
michael@202 | 1298 | + int wd3; |
michael@202 | 1299 | + int eh; |
michael@202 | 1300 | + int mih; |
michael@202 | 1301 | + int i; |
michael@202 | 1302 | + int j; |
michael@202 | 1303 | + /* Low and high band PCM from the QMF */ |
michael@202 | 1304 | + int xlow; |
michael@202 | 1305 | + int xhigh; |
michael@202 | 1306 | + int g722_bytes; |
michael@202 | 1307 | + /* Even and odd tap accumulators */ |
michael@202 | 1308 | + int sumeven; |
michael@202 | 1309 | + int sumodd; |
michael@202 | 1310 | + int ihigh; |
michael@202 | 1311 | + int ilow; |
michael@202 | 1312 | + int code; |
michael@202 | 1313 | + |
michael@202 | 1314 | + g722_bytes = 0; |
michael@202 | 1315 | + xhigh = 0; |
michael@202 | 1316 | + for (j = 0; j < len; ) |
michael@202 | 1317 | + { |
michael@202 | 1318 | + if (s->itu_test_mode) |
michael@202 | 1319 | + { |
michael@202 | 1320 | + xlow = |
michael@202 | 1321 | + xhigh = amp[j++] >> 1; |
michael@202 | 1322 | + } |
michael@202 | 1323 | + else |
michael@202 | 1324 | + { |
michael@202 | 1325 | + if (s->eight_k) |
michael@202 | 1326 | + { |
michael@202 | 1327 | + xlow = amp[j++]; |
michael@202 | 1328 | + } |
michael@202 | 1329 | + else |
michael@202 | 1330 | + { |
michael@202 | 1331 | + /* Apply the transmit QMF */ |
michael@202 | 1332 | + /* Shuffle the buffer down */ |
michael@202 | 1333 | + for (i = 0; i < 22; i++) |
michael@202 | 1334 | + s->x[i] = s->x[i + 2]; |
michael@202 | 1335 | + s->x[22] = amp[j++]; |
michael@202 | 1336 | + s->x[23] = amp[j++]; |
michael@202 | 1337 | + |
michael@202 | 1338 | + /* Discard every other QMF output */ |
michael@202 | 1339 | + sumeven = 0; |
michael@202 | 1340 | + sumodd = 0; |
michael@202 | 1341 | + for (i = 0; i < 12; i++) |
michael@202 | 1342 | + { |
michael@202 | 1343 | + sumodd += s->x[2*i]*qmf_coeffs[i]; |
michael@202 | 1344 | + sumeven += s->x[2*i + 1]*qmf_coeffs[11 - i]; |
michael@202 | 1345 | + } |
michael@202 | 1346 | + xlow = (sumeven + sumodd) >> 13; |
michael@202 | 1347 | + xhigh = (sumeven - sumodd) >> 13; |
michael@202 | 1348 | + } |
michael@202 | 1349 | + } |
michael@202 | 1350 | + /* Block 1L, SUBTRA */ |
michael@202 | 1351 | + el = saturate(xlow - s->band[0].s); |
michael@202 | 1352 | + |
michael@202 | 1353 | + /* Block 1L, QUANTL */ |
michael@202 | 1354 | + wd = (el >= 0) ? el : -(el + 1); |
michael@202 | 1355 | + |
michael@202 | 1356 | + for (i = 1; i < 30; i++) |
michael@202 | 1357 | + { |
michael@202 | 1358 | + wd1 = (q6[i]*s->band[0].det) >> 12; |
michael@202 | 1359 | + if (wd < wd1) |
michael@202 | 1360 | + break; |
michael@202 | 1361 | + } |
michael@202 | 1362 | + ilow = (el < 0) ? iln[i] : ilp[i]; |
michael@202 | 1363 | + |
michael@202 | 1364 | + /* Block 2L, INVQAL */ |
michael@202 | 1365 | + ril = ilow >> 2; |
michael@202 | 1366 | + wd2 = qm4[ril]; |
michael@202 | 1367 | + dlow = (s->band[0].det*wd2) >> 15; |
michael@202 | 1368 | + |
michael@202 | 1369 | + /* Block 3L, LOGSCL */ |
michael@202 | 1370 | + il4 = rl42[ril]; |
michael@202 | 1371 | + wd = (s->band[0].nb*127) >> 7; |
michael@202 | 1372 | + s->band[0].nb = wd + wl[il4]; |
michael@202 | 1373 | + if (s->band[0].nb < 0) |
michael@202 | 1374 | + s->band[0].nb = 0; |
michael@202 | 1375 | + else if (s->band[0].nb > 18432) |
michael@202 | 1376 | + s->band[0].nb = 18432; |
michael@202 | 1377 | + |
michael@202 | 1378 | + /* Block 3L, SCALEL */ |
michael@202 | 1379 | + wd1 = (s->band[0].nb >> 6) & 31; |
michael@202 | 1380 | + wd2 = 8 - (s->band[0].nb >> 11); |
michael@202 | 1381 | + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); |
michael@202 | 1382 | + s->band[0].det = wd3 << 2; |
michael@202 | 1383 | + |
michael@202 | 1384 | + block4(s, 0, dlow); |
michael@202 | 1385 | + |
michael@202 | 1386 | + if (s->eight_k) |
michael@202 | 1387 | + { |
michael@202 | 1388 | + /* Just leave the high bits as zero */ |
michael@202 | 1389 | + code = (0xC0 | ilow) >> (8 - s->bits_per_sample); |
michael@202 | 1390 | + } |
michael@202 | 1391 | + else |
michael@202 | 1392 | + { |
michael@202 | 1393 | + /* Block 1H, SUBTRA */ |
michael@202 | 1394 | + eh = saturate(xhigh - s->band[1].s); |
michael@202 | 1395 | + |
michael@202 | 1396 | + /* Block 1H, QUANTH */ |
michael@202 | 1397 | + wd = (eh >= 0) ? eh : -(eh + 1); |
michael@202 | 1398 | + wd1 = (564*s->band[1].det) >> 12; |
michael@202 | 1399 | + mih = (wd >= wd1) ? 2 : 1; |
michael@202 | 1400 | + ihigh = (eh < 0) ? ihn[mih] : ihp[mih]; |
michael@202 | 1401 | + |
michael@202 | 1402 | + /* Block 2H, INVQAH */ |
michael@202 | 1403 | + wd2 = qm2[ihigh]; |
michael@202 | 1404 | + dhigh = (s->band[1].det*wd2) >> 15; |
michael@202 | 1405 | + |
michael@202 | 1406 | + /* Block 3H, LOGSCH */ |
michael@202 | 1407 | + ih2 = rh2[ihigh]; |
michael@202 | 1408 | + wd = (s->band[1].nb*127) >> 7; |
michael@202 | 1409 | + s->band[1].nb = wd + wh[ih2]; |
michael@202 | 1410 | + if (s->band[1].nb < 0) |
michael@202 | 1411 | + s->band[1].nb = 0; |
michael@202 | 1412 | + else if (s->band[1].nb > 22528) |
michael@202 | 1413 | + s->band[1].nb = 22528; |
michael@202 | 1414 | + |
michael@202 | 1415 | + /* Block 3H, SCALEH */ |
michael@202 | 1416 | + wd1 = (s->band[1].nb >> 6) & 31; |
michael@202 | 1417 | + wd2 = 10 - (s->band[1].nb >> 11); |
michael@202 | 1418 | + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); |
michael@202 | 1419 | + s->band[1].det = wd3 << 2; |
michael@202 | 1420 | + |
michael@202 | 1421 | + block4(s, 1, dhigh); |
michael@202 | 1422 | + code = ((ihigh << 6) | ilow) >> (8 - s->bits_per_sample); |
michael@202 | 1423 | + } |
michael@202 | 1424 | + |
michael@202 | 1425 | + if (s->packed) |
michael@202 | 1426 | + { |
michael@202 | 1427 | + /* Pack the code bits */ |
michael@202 | 1428 | + s->out_buffer |= (code << s->out_bits); |
michael@202 | 1429 | + s->out_bits += s->bits_per_sample; |
michael@202 | 1430 | + if (s->out_bits >= 8) |
michael@202 | 1431 | + { |
michael@202 | 1432 | + g722_data[g722_bytes++] = (uint8_t) (s->out_buffer & 0xFF); |
michael@202 | 1433 | + s->out_bits -= 8; |
michael@202 | 1434 | + s->out_buffer >>= 8; |
michael@202 | 1435 | + } |
michael@202 | 1436 | + } |
michael@202 | 1437 | + else |
michael@202 | 1438 | + { |
michael@202 | 1439 | + g722_data[g722_bytes++] = (uint8_t) code; |
michael@202 | 1440 | + } |
michael@202 | 1441 | + } |
michael@202 | 1442 | + return g722_bytes; |
michael@202 | 1443 | +} |
michael@202 | 1444 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 1445 | +/*- End of file ------------------------------------------------------------*/ |
michael@202 | 1446 | Index: codecs/g722/g722.h |
michael@202 | 1447 | diff -Nau codecs/g722/g722.h.orig codecs/g722/g722.h |
michael@202 | 1448 | --- codecs/g722/g722.h.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 1449 | +++ codecs/g722/g722.h 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1450 | @@ -0,0 +1,148 @@ |
michael@202 | 1451 | +/* |
michael@202 | 1452 | + * SpanDSP - a series of DSP components for telephony |
michael@202 | 1453 | + * |
michael@202 | 1454 | + * g722.h - The ITU G.722 codec. |
michael@202 | 1455 | + * |
michael@202 | 1456 | + * Written by Steve Underwood <steveu@coppice.org> |
michael@202 | 1457 | + * |
michael@202 | 1458 | + * Copyright (C) 2005 Steve Underwood |
michael@202 | 1459 | + * |
michael@202 | 1460 | + * Despite my general liking of the GPL, I place my own contributions |
michael@202 | 1461 | + * to this code in the public domain for the benefit of all mankind - |
michael@202 | 1462 | + * even the slimy ones who might try to proprietize my work and use it |
michael@202 | 1463 | + * to my detriment. |
michael@202 | 1464 | + * |
michael@202 | 1465 | + * Based on a single channel G.722 codec which is: |
michael@202 | 1466 | + * |
michael@202 | 1467 | + ***** Copyright (c) CMU 1993 ***** |
michael@202 | 1468 | + * Computer Science, Speech Group |
michael@202 | 1469 | + * Chengxiang Lu and Alex Hauptmann |
michael@202 | 1470 | + * |
michael@202 | 1471 | + * $Id: g722.h 48959 2006-12-25 06:42:15Z rizzo $ |
michael@202 | 1472 | + */ |
michael@202 | 1473 | + |
michael@202 | 1474 | + |
michael@202 | 1475 | +/*! \file */ |
michael@202 | 1476 | + |
michael@202 | 1477 | +#if !defined(_G722_H_) |
michael@202 | 1478 | +#define _G722_H_ |
michael@202 | 1479 | + |
michael@202 | 1480 | +/*! \page g722_page G.722 encoding and decoding |
michael@202 | 1481 | +\section g722_page_sec_1 What does it do? |
michael@202 | 1482 | +The G.722 module is a bit exact implementation of the ITU G.722 specification for all three |
michael@202 | 1483 | +specified bit rates - 64000bps, 56000bps and 48000bps. It passes the ITU tests. |
michael@202 | 1484 | + |
michael@202 | 1485 | +To allow fast and flexible interworking with narrow band telephony, the encoder and decoder |
michael@202 | 1486 | +support an option for the linear audio to be an 8k samples/second stream. In this mode the |
michael@202 | 1487 | +codec is considerably faster, and still fully compatible with wideband terminals using G.722. |
michael@202 | 1488 | + |
michael@202 | 1489 | +\section g722_page_sec_2 How does it work? |
michael@202 | 1490 | +???. |
michael@202 | 1491 | +*/ |
michael@202 | 1492 | + |
michael@202 | 1493 | +enum |
michael@202 | 1494 | +{ |
michael@202 | 1495 | + G722_SAMPLE_RATE_8000 = 0x0001, |
michael@202 | 1496 | + G722_PACKED = 0x0002 |
michael@202 | 1497 | +}; |
michael@202 | 1498 | + |
michael@202 | 1499 | +#ifndef INT16_MAX |
michael@202 | 1500 | +#define INT16_MAX 32767 |
michael@202 | 1501 | +#endif |
michael@202 | 1502 | +#ifndef INT16_MIN |
michael@202 | 1503 | +#define INT16_MIN (-32768) |
michael@202 | 1504 | +#endif |
michael@202 | 1505 | + |
michael@202 | 1506 | +typedef struct |
michael@202 | 1507 | +{ |
michael@202 | 1508 | + /*! TRUE if the operating in the special ITU test mode, with the band split filters |
michael@202 | 1509 | + disabled. */ |
michael@202 | 1510 | + int itu_test_mode; |
michael@202 | 1511 | + /*! TRUE if the G.722 data is packed */ |
michael@202 | 1512 | + int packed; |
michael@202 | 1513 | + /*! TRUE if encode from 8k samples/second */ |
michael@202 | 1514 | + int eight_k; |
michael@202 | 1515 | + /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */ |
michael@202 | 1516 | + int bits_per_sample; |
michael@202 | 1517 | + |
michael@202 | 1518 | + /*! Signal history for the QMF */ |
michael@202 | 1519 | + int x[24]; |
michael@202 | 1520 | + |
michael@202 | 1521 | + struct |
michael@202 | 1522 | + { |
michael@202 | 1523 | + int s; |
michael@202 | 1524 | + int sp; |
michael@202 | 1525 | + int sz; |
michael@202 | 1526 | + int r[3]; |
michael@202 | 1527 | + int a[3]; |
michael@202 | 1528 | + int ap[3]; |
michael@202 | 1529 | + int p[3]; |
michael@202 | 1530 | + int d[7]; |
michael@202 | 1531 | + int b[7]; |
michael@202 | 1532 | + int bp[7]; |
michael@202 | 1533 | + int sg[7]; |
michael@202 | 1534 | + int nb; |
michael@202 | 1535 | + int det; |
michael@202 | 1536 | + } band[2]; |
michael@202 | 1537 | + |
michael@202 | 1538 | + unsigned int in_buffer; |
michael@202 | 1539 | + int in_bits; |
michael@202 | 1540 | + unsigned int out_buffer; |
michael@202 | 1541 | + int out_bits; |
michael@202 | 1542 | +} g722_encode_state_t; |
michael@202 | 1543 | + |
michael@202 | 1544 | +typedef struct |
michael@202 | 1545 | +{ |
michael@202 | 1546 | + /*! TRUE if the operating in the special ITU test mode, with the band split filters |
michael@202 | 1547 | + disabled. */ |
michael@202 | 1548 | + int itu_test_mode; |
michael@202 | 1549 | + /*! TRUE if the G.722 data is packed */ |
michael@202 | 1550 | + int packed; |
michael@202 | 1551 | + /*! TRUE if decode to 8k samples/second */ |
michael@202 | 1552 | + int eight_k; |
michael@202 | 1553 | + /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */ |
michael@202 | 1554 | + int bits_per_sample; |
michael@202 | 1555 | + |
michael@202 | 1556 | + /*! Signal history for the QMF */ |
michael@202 | 1557 | + int x[24]; |
michael@202 | 1558 | + |
michael@202 | 1559 | + struct |
michael@202 | 1560 | + { |
michael@202 | 1561 | + int s; |
michael@202 | 1562 | + int sp; |
michael@202 | 1563 | + int sz; |
michael@202 | 1564 | + int r[3]; |
michael@202 | 1565 | + int a[3]; |
michael@202 | 1566 | + int ap[3]; |
michael@202 | 1567 | + int p[3]; |
michael@202 | 1568 | + int d[7]; |
michael@202 | 1569 | + int b[7]; |
michael@202 | 1570 | + int bp[7]; |
michael@202 | 1571 | + int sg[7]; |
michael@202 | 1572 | + int nb; |
michael@202 | 1573 | + int det; |
michael@202 | 1574 | + } band[2]; |
michael@202 | 1575 | + |
michael@202 | 1576 | + unsigned int in_buffer; |
michael@202 | 1577 | + int in_bits; |
michael@202 | 1578 | + unsigned int out_buffer; |
michael@202 | 1579 | + int out_bits; |
michael@202 | 1580 | +} g722_decode_state_t; |
michael@202 | 1581 | + |
michael@202 | 1582 | +#ifdef __cplusplus |
michael@202 | 1583 | +extern "C" { |
michael@202 | 1584 | +#endif |
michael@202 | 1585 | + |
michael@202 | 1586 | +g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options); |
michael@202 | 1587 | +int g722_encode_release(g722_encode_state_t *s); |
michael@202 | 1588 | +int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len); |
michael@202 | 1589 | + |
michael@202 | 1590 | +g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options); |
michael@202 | 1591 | +int g722_decode_release(g722_decode_state_t *s); |
michael@202 | 1592 | +int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len); |
michael@202 | 1593 | + |
michael@202 | 1594 | +#ifdef __cplusplus |
michael@202 | 1595 | +} |
michael@202 | 1596 | +#endif |
michael@202 | 1597 | + |
michael@202 | 1598 | +#endif |
michael@202 | 1599 | Index: codecs/g722/Makefile |
michael@202 | 1600 | diff -Nau codecs/g722/Makefile.orig codecs/g722/Makefile |
michael@202 | 1601 | --- codecs/g722/Makefile.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 1602 | +++ codecs/g722/Makefile 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1603 | @@ -0,0 +1,18 @@ |
michael@202 | 1604 | +LIB=libg722.a |
michael@202 | 1605 | +CFLAGS+=-fPIC |
michael@202 | 1606 | + |
michael@202 | 1607 | +include $(ASTTOPDIR)/Makefile.rules |
michael@202 | 1608 | + |
michael@202 | 1609 | +OBJS=g722_encode.o g722_decode.o |
michael@202 | 1610 | + |
michael@202 | 1611 | +all: $(LIB) |
michael@202 | 1612 | + |
michael@202 | 1613 | +$(LIB): $(OBJS) |
michael@202 | 1614 | + $(ECHO_PREFIX) echo " [AR] $^ -> $@" |
michael@202 | 1615 | + $(CMD_PREFIX) $(AR) cr $@ $^ |
michael@202 | 1616 | + $(CMD_PREFIX) $(RANLIB) $@ |
michael@202 | 1617 | + |
michael@202 | 1618 | +clean: |
michael@202 | 1619 | + rm -f $(LIB) *.o |
michael@202 | 1620 | + rm -f .*.o.d |
michael@202 | 1621 | + rm -f *.s *.i |
michael@202 | 1622 | Index: codecs/g722_slin_ex.h |
michael@202 | 1623 | diff -Nau codecs/g722_slin_ex.h.orig codecs/g722_slin_ex.h |
michael@202 | 1624 | --- codecs/g722_slin_ex.h.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 1625 | +++ codecs/g722_slin_ex.h 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1626 | @@ -0,0 +1,25 @@ |
michael@202 | 1627 | +/*! \file |
michael@202 | 1628 | + * \brief g722_slin_ex.h -- |
michael@202 | 1629 | + * |
michael@202 | 1630 | + * 4-bit ADPCM data, 20 milliseconds worth at 8 kHz. |
michael@202 | 1631 | + * |
michael@202 | 1632 | + * Source: g723.example |
michael@202 | 1633 | + * |
michael@202 | 1634 | + * Copyright (C) 2001-2005, Digium Inc. |
michael@202 | 1635 | + * |
michael@202 | 1636 | + * Distributed under the terms of the GNU General Public License |
michael@202 | 1637 | + * |
michael@202 | 1638 | + */ |
michael@202 | 1639 | + |
michael@202 | 1640 | +static unsigned char g722_slin_ex[] = { |
michael@202 | 1641 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1642 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1643 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1644 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1645 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1646 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1647 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1648 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1649 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1650 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
michael@202 | 1651 | +}; |
michael@202 | 1652 | Index: codecs/Makefile |
michael@202 | 1653 | diff -Nau codecs/Makefile.orig codecs/Makefile |
michael@202 | 1654 | --- codecs/Makefile.orig 2008-03-26 17:42:35.000000000 +0100 |
michael@202 | 1655 | +++ codecs/Makefile 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1656 | @@ -31,6 +31,7 @@ |
michael@202 | 1657 | |
michael@202 | 1658 | LIBILBC:=ilbc/libilbc.a |
michael@202 | 1659 | LIBLPC10:=lpc10/liblpc10.a |
michael@202 | 1660 | +LIBG722:=g722/libg722.a |
michael@202 | 1661 | |
michael@202 | 1662 | all: _all |
michael@202 | 1663 | |
michael@202 | 1664 | @@ -45,6 +46,7 @@ |
michael@202 | 1665 | $(MAKE) -C gsm clean |
michael@202 | 1666 | $(MAKE) -C lpc10 clean |
michael@202 | 1667 | $(MAKE) -C ilbc clean |
michael@202 | 1668 | + $(MAKE) -C g722 clean |
michael@202 | 1669 | |
michael@202 | 1670 | gsm/lib/libgsm.a: |
michael@202 | 1671 | @mkdir -p gsm/lib |
michael@202 | 1672 | @@ -59,3 +61,8 @@ |
michael@202 | 1673 | @$(MAKE) -C ilbc all ASTCFLAGS="$(filter-out -Wmissing-prototypes -Wmissing-declarations,$(ASTCFLAGS)) $(AST_NO_STRICT_OVERFLOW)" |
michael@202 | 1674 | |
michael@202 | 1675 | $(if $(filter codec_ilbc,$(EMBEDDED_MODS)),modules.link,codec_ilbc.so): $(LIBILBC) |
michael@202 | 1676 | + |
michael@202 | 1677 | +$(LIBG722): |
michael@202 | 1678 | + @$(MAKE) -C g722 all |
michael@202 | 1679 | + |
michael@202 | 1680 | +$(if $(filter codec_g722,$(EMBEDDED_MODS)),modules.link,codec_g722.so): $(LIBG722) |
michael@202 | 1681 | Index: codecs/slin_g722_ex.h |
michael@202 | 1682 | diff -Nau codecs/slin_g722_ex.h.orig codecs/slin_g722_ex.h |
michael@202 | 1683 | --- codecs/slin_g722_ex.h.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 1684 | +++ codecs/slin_g722_ex.h 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1685 | @@ -0,0 +1,25 @@ |
michael@202 | 1686 | +/*! \file |
michael@202 | 1687 | + * \brief slin_g722_ex.h -- |
michael@202 | 1688 | + * |
michael@202 | 1689 | + * Signed 16-bit audio data, 10 milliseconds worth at 8 kHz. |
michael@202 | 1690 | + * |
michael@202 | 1691 | + * Source: g723.example |
michael@202 | 1692 | + * |
michael@202 | 1693 | + * Copyright (C) 2001-2005, Digium Inc. |
michael@202 | 1694 | + * |
michael@202 | 1695 | + * Distributed under the terms of the GNU General Public License |
michael@202 | 1696 | + * |
michael@202 | 1697 | + */ |
michael@202 | 1698 | + |
michael@202 | 1699 | +static signed short slin_g722_ex[] = { |
michael@202 | 1700 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1701 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1702 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1703 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1704 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1705 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1706 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1707 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1708 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1709 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 |
michael@202 | 1710 | +}; |
michael@202 | 1711 | Index: configure |
michael@202 | 1712 | diff -Nau configure.orig configure |
michael@202 | 1713 | --- configure.orig 2009-02-18 21:06:45.000000000 +0100 |
michael@202 | 1714 | +++ configure 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1715 | @@ -11143,6 +11143,61 @@ |
michael@202 | 1716 | |
michael@202 | 1717 | fi |
michael@202 | 1718 | |
michael@202 | 1719 | +{ echo "$as_me:$LINENO: checking for tm_gmtoff in struct tm" >&5 |
michael@202 | 1720 | +echo $ECHO_N "checking for tm_gmtoff in struct tm... $ECHO_C" >&6; } |
michael@202 | 1721 | +if test "${ac_cv_struct_tm_gmtoff+set}" = set; then |
michael@202 | 1722 | + echo $ECHO_N "(cached) $ECHO_C" >&6 |
michael@202 | 1723 | +else |
michael@202 | 1724 | + cat >conftest.$ac_ext <<_ACEOF |
michael@202 | 1725 | +/* confdefs.h. */ |
michael@202 | 1726 | +_ACEOF |
michael@202 | 1727 | +cat confdefs.h >>conftest.$ac_ext |
michael@202 | 1728 | +cat >>conftest.$ac_ext <<_ACEOF |
michael@202 | 1729 | +/* end confdefs.h. */ |
michael@202 | 1730 | +$ac_includes_default |
michael@202 | 1731 | +#include <sys/types.h> |
michael@202 | 1732 | +#include <$ac_cv_struct_tm> |
michael@202 | 1733 | +int main() { |
michael@202 | 1734 | +struct tm tm; tm.tm_gmtoff; |
michael@202 | 1735 | +; return 0; } |
michael@202 | 1736 | +_ACEOF |
michael@202 | 1737 | +rm -f conftest.$ac_objext |
michael@202 | 1738 | +if { (ac_try="$ac_compile" |
michael@202 | 1739 | +case "(($ac_try" in |
michael@202 | 1740 | + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; |
michael@202 | 1741 | + *) ac_try_echo=$ac_try;; |
michael@202 | 1742 | +esac |
michael@202 | 1743 | +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 |
michael@202 | 1744 | + (eval "$ac_compile") 2>conftest.er1 |
michael@202 | 1745 | + ac_status=$? |
michael@202 | 1746 | + grep -v '^ *+' conftest.er1 >conftest.err |
michael@202 | 1747 | + rm -f conftest.er1 |
michael@202 | 1748 | + cat conftest.err >&5 |
michael@202 | 1749 | + echo "$as_me:$LINENO: \$? = $ac_status" >&5 |
michael@202 | 1750 | + (exit $ac_status); } && { |
michael@202 | 1751 | + test -z "$ac_c_werror_flag" || |
michael@202 | 1752 | + test ! -s conftest.err |
michael@202 | 1753 | + } && test -s conftest.$ac_objext; then |
michael@202 | 1754 | + ac_cv_struct_tm_gmtoff=yes |
michael@202 | 1755 | +else |
michael@202 | 1756 | + echo "$as_me: failed program was:" >&5 |
michael@202 | 1757 | +sed 's/^/| /' conftest.$ac_ext >&5 |
michael@202 | 1758 | + |
michael@202 | 1759 | + ac_cv_struct_tm_gmtoff=no |
michael@202 | 1760 | +fi |
michael@202 | 1761 | + |
michael@202 | 1762 | +rm -f conftest* |
michael@202 | 1763 | +fi |
michael@202 | 1764 | +{ echo "$as_me:$LINENO: result: $ac_cv_struct_tm_gmtoff" >&5 |
michael@202 | 1765 | +echo "${ECHO_T}$ac_cv_struct_tm_gmtoff" >&6; } |
michael@202 | 1766 | +if test $ac_cv_struct_tm_gmtoff = yes; then |
michael@202 | 1767 | + |
michael@202 | 1768 | +cat >>confdefs.h <<\_ACEOF |
michael@202 | 1769 | +#define TM_GMTOFF 1 |
michael@202 | 1770 | +_ACEOF |
michael@202 | 1771 | + |
michael@202 | 1772 | +fi |
michael@202 | 1773 | + |
michael@202 | 1774 | { echo "$as_me:$LINENO: checking for working volatile" >&5 |
michael@202 | 1775 | echo $ECHO_N "checking for working volatile... $ECHO_C" >&6; } |
michael@202 | 1776 | if test "${ac_cv_c_volatile+set}" = set; then |
michael@202 | 1777 | Index: include/asterisk/config.h |
michael@202 | 1778 | diff -Nau include/asterisk/config.h.orig include/asterisk/config.h |
michael@202 | 1779 | --- include/asterisk/config.h.orig 2009-02-18 19:30:38.000000000 +0100 |
michael@202 | 1780 | +++ include/asterisk/config.h 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1781 | @@ -33,6 +33,8 @@ |
michael@202 | 1782 | |
michael@202 | 1783 | struct ast_category; |
michael@202 | 1784 | |
michael@202 | 1785 | +#define CONFIG_STATUS_FILEUNCHANGED (void *)-1 |
michael@202 | 1786 | + |
michael@202 | 1787 | struct ast_variable { |
michael@202 | 1788 | char *name; |
michael@202 | 1789 | char *value; |
michael@202 | 1790 | Index: include/asterisk/frame.h |
michael@202 | 1791 | diff -Nau include/asterisk/frame.h.orig include/asterisk/frame.h |
michael@202 | 1792 | --- include/asterisk/frame.h.orig 2009-03-05 19:22:16.000000000 +0100 |
michael@202 | 1793 | +++ include/asterisk/frame.h 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1794 | @@ -260,6 +260,8 @@ |
michael@202 | 1795 | #define AST_FORMAT_G726 (1 << 11) |
michael@202 | 1796 | /*! G.722 */ |
michael@202 | 1797 | #define AST_FORMAT_G722 (1 << 12) |
michael@202 | 1798 | +/*! Raw 16-bit Signed Linear (16000 Hz) PCM */ |
michael@202 | 1799 | +#define AST_FORMAT_SLINEAR16 (1 << 15) |
michael@202 | 1800 | /*! Unsupported audio bits */ |
michael@202 | 1801 | #define AST_FORMAT_AUDIO_UNDEFINED ((1 << 13) | (1 << 14) | (1 << 15)) |
michael@202 | 1802 | /*! Maximum audio format */ |
michael@202 | 1803 | Index: main/editline/np/vis.h |
michael@202 | 1804 | diff -Nau main/editline/np/vis.h.orig main/editline/np/vis.h |
michael@202 | 1805 | --- main/editline/np/vis.h.orig 2006-08-21 04:11:39.000000000 +0200 |
michael@202 | 1806 | +++ main/editline/np/vis.h 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1807 | @@ -76,6 +76,22 @@ |
michael@202 | 1808 | |
michael@202 | 1809 | #include <sys/cdefs.h> |
michael@202 | 1810 | |
michael@202 | 1811 | +/* correct nonportable unsigned type usage */ |
michael@202 | 1812 | +#if !defined(__FreeBSD__) && !defined(__linux__) |
michael@202 | 1813 | +#ifndef u_int64_t |
michael@202 | 1814 | +#define u_int64_t unsigned long long |
michael@202 | 1815 | +#endif |
michael@202 | 1816 | +#ifndef u_int32_t |
michael@202 | 1817 | +#define u_int32_t unsigned int |
michael@202 | 1818 | +#endif |
michael@202 | 1819 | +#ifndef u_int16_t |
michael@202 | 1820 | +#define u_int16_t unsigned short |
michael@202 | 1821 | +#endif |
michael@202 | 1822 | +#ifndef u_int6_t |
michael@202 | 1823 | +#define u_int8_t unsigned char |
michael@202 | 1824 | +#endif |
michael@202 | 1825 | +#endif |
michael@202 | 1826 | + |
michael@202 | 1827 | __BEGIN_DECLS |
michael@202 | 1828 | char *vis __P((char *, int, int, int)); |
michael@202 | 1829 | char *svis __P((char *, int, int, int, const char *)); |
michael@202 | 1830 | Index: main/stdtime/localtime.c |
michael@202 | 1831 | diff -Nau main/stdtime/localtime.c.orig main/stdtime/localtime.c |
michael@202 | 1832 | --- main/stdtime/localtime.c.orig 2008-09-27 17:00:48.000000000 +0200 |
michael@202 | 1833 | +++ main/stdtime/localtime.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1834 | @@ -1134,9 +1134,9 @@ |
michael@202 | 1835 | */ |
michael@202 | 1836 | result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); |
michael@202 | 1837 | tmp->tm_isdst = ttisp->tt_isdst; |
michael@202 | 1838 | -#ifndef SOLARIS /* Solaris doesn't have this element */ |
michael@202 | 1839 | +#ifdef TM_GMTOFF |
michael@202 | 1840 | tmp->tm_gmtoff = ttisp->tt_gmtoff; |
michael@202 | 1841 | -#endif |
michael@202 | 1842 | +#endif /* defined TM_GMTOFF */ |
michael@202 | 1843 | #ifdef TM_ZONE |
michael@202 | 1844 | tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; |
michael@202 | 1845 | #endif /* defined TM_ZONE */ |
michael@202 | 1846 | Index: Makefile.moddir_rules |
michael@202 | 1847 | diff -Nau Makefile.moddir_rules.orig Makefile.moddir_rules |
michael@202 | 1848 | --- Makefile.moddir_rules.orig 2008-11-26 19:36:24.000000000 +0100 |
michael@202 | 1849 | +++ Makefile.moddir_rules 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1850 | @@ -69,7 +69,9 @@ |
michael@202 | 1851 | rm -f modules.link |
michael@202 | 1852 | |
michael@202 | 1853 | install:: all |
michael@202 | 1854 | +ifneq ($(LOADABLE_MODS),) |
michael@202 | 1855 | for x in $(LOADABLE_MODS:%=%.so); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done |
michael@202 | 1856 | +endif |
michael@202 | 1857 | |
michael@202 | 1858 | uninstall:: |
michael@202 | 1859 | |
michael@202 | 1860 | Index: res/res_features.c |
michael@202 | 1861 | diff -Nau res/res_features.c.orig res/res_features.c |
michael@202 | 1862 | --- res/res_features.c.orig 2009-03-03 19:27:09.000000000 +0100 |
michael@202 | 1863 | +++ res/res_features.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1864 | @@ -732,6 +732,10 @@ |
michael@202 | 1865 | snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename); |
michael@202 | 1866 | } |
michael@202 | 1867 | |
michael@202 | 1868 | + for( x = 0; x < strlen(touch_filename); x++) { |
michael@202 | 1869 | + if (touch_filename[x] == '/') |
michael@202 | 1870 | + touch_filename[x] = '-'; |
michael@202 | 1871 | + } |
michael@202 | 1872 | for( x = 0; x < strlen(args); x++) { |
michael@202 | 1873 | if (args[x] == '/') |
michael@202 | 1874 | args[x] = '-'; |
michael@202 | 1875 | @@ -2774,6 +2778,293 @@ |
michael@202 | 1876 | } |
michael@202 | 1877 | } |
michael@202 | 1878 | |
michael@202 | 1879 | +static char mandescr_bridge[] = |
michael@202 | 1880 | +"Description: Bridge together two channels already in the PBX\n" |
michael@202 | 1881 | +"Variables: ( Headers marked with * are required )\n" |
michael@202 | 1882 | +" *Channel1: Channel to Bridge to Channel2\n" |
michael@202 | 1883 | +" *Channel2: Channel to Bridge to Channel1\n" |
michael@202 | 1884 | +" Tone: (Yes|No) Play courtesy tone to Channel 2\n" |
michael@202 | 1885 | +"\n"; |
michael@202 | 1886 | + |
michael@202 | 1887 | +/*! |
michael@202 | 1888 | + * \brief Actual bridge |
michael@202 | 1889 | + * \param chan |
michael@202 | 1890 | + * \param tmpchan |
michael@202 | 1891 | + * |
michael@202 | 1892 | + * Stop hold music, lock both channels, masq channels, |
michael@202 | 1893 | + * after bridge return channel to next priority. |
michael@202 | 1894 | +*/ |
michael@202 | 1895 | +static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan) |
michael@202 | 1896 | +{ |
michael@202 | 1897 | + ast_moh_stop(chan); |
michael@202 | 1898 | + ast_channel_lock(chan); |
michael@202 | 1899 | + ast_setstate(tmpchan, chan->_state); |
michael@202 | 1900 | + tmpchan->readformat = chan->readformat; |
michael@202 | 1901 | + tmpchan->writeformat = chan->writeformat; |
michael@202 | 1902 | + ast_channel_masquerade(tmpchan, chan); |
michael@202 | 1903 | + ast_channel_lock(tmpchan); |
michael@202 | 1904 | + ast_do_masquerade(tmpchan); |
michael@202 | 1905 | + /* when returning from bridge, the channel will continue at the next priority */ |
michael@202 | 1906 | + ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1); |
michael@202 | 1907 | + ast_channel_unlock(tmpchan); |
michael@202 | 1908 | + ast_channel_unlock(chan); |
michael@202 | 1909 | +} |
michael@202 | 1910 | + |
michael@202 | 1911 | +/*! |
michael@202 | 1912 | + * \brief Bridge channels together |
michael@202 | 1913 | + * \param s |
michael@202 | 1914 | + * \param m |
michael@202 | 1915 | + * |
michael@202 | 1916 | + * Make sure valid channels were specified, |
michael@202 | 1917 | + * send errors if any of the channels could not be found/locked, answer channels if needed, |
michael@202 | 1918 | + * create the placeholder channels and grab the other channels |
michael@202 | 1919 | + * make the channels compatible, send error if we fail doing so |
michael@202 | 1920 | + * setup the bridge thread object and start the bridge. |
michael@202 | 1921 | + * |
michael@202 | 1922 | + * \retval 0 on success or on incorrect use. |
michael@202 | 1923 | + * \retval 1 on failure to bridge channels. |
michael@202 | 1924 | +*/ |
michael@202 | 1925 | +static int action_bridge(struct mansession *s, const struct message *m) |
michael@202 | 1926 | +{ |
michael@202 | 1927 | + const char *channela = astman_get_header(m, "Channel1"); |
michael@202 | 1928 | + const char *channelb = astman_get_header(m, "Channel2"); |
michael@202 | 1929 | + const char *playtone = astman_get_header(m, "Tone"); |
michael@202 | 1930 | + struct ast_channel *chana = NULL, *chanb = NULL; |
michael@202 | 1931 | + struct ast_channel *tmpchana = NULL, *tmpchanb = NULL; |
michael@202 | 1932 | + struct ast_bridge_thread_obj *tobj = NULL; |
michael@202 | 1933 | + |
michael@202 | 1934 | + /* make sure valid channels were specified */ |
michael@202 | 1935 | + if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) { |
michael@202 | 1936 | + chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela)); |
michael@202 | 1937 | + chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb)); |
michael@202 | 1938 | + if (chana) |
michael@202 | 1939 | + ast_channel_unlock(chana); |
michael@202 | 1940 | + if (chanb) |
michael@202 | 1941 | + ast_channel_unlock(chanb); |
michael@202 | 1942 | + |
michael@202 | 1943 | + /* send errors if any of the channels could not be found/locked */ |
michael@202 | 1944 | + if (!chana) { |
michael@202 | 1945 | + char buf[256]; |
michael@202 | 1946 | + snprintf(buf, sizeof(buf), "Channel1 does not exist: %s", channela); |
michael@202 | 1947 | + astman_send_error(s, m, buf); |
michael@202 | 1948 | + return 0; |
michael@202 | 1949 | + } |
michael@202 | 1950 | + if (!chanb) { |
michael@202 | 1951 | + char buf[256]; |
michael@202 | 1952 | + snprintf(buf, sizeof(buf), "Channel2 does not exist: %s", channelb); |
michael@202 | 1953 | + astman_send_error(s, m, buf); |
michael@202 | 1954 | + return 0; |
michael@202 | 1955 | + } |
michael@202 | 1956 | + } else { |
michael@202 | 1957 | + astman_send_error(s, m, "Missing channel parameter in request"); |
michael@202 | 1958 | + return 0; |
michael@202 | 1959 | + } |
michael@202 | 1960 | + |
michael@202 | 1961 | + /* Answer the channels if needed */ |
michael@202 | 1962 | + if (chana->_state != AST_STATE_UP) |
michael@202 | 1963 | + ast_answer(chana); |
michael@202 | 1964 | + if (chanb->_state != AST_STATE_UP) |
michael@202 | 1965 | + ast_answer(chanb); |
michael@202 | 1966 | + |
michael@202 | 1967 | + /* create the placeholder channels and grab the other channels */ |
michael@202 | 1968 | + if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, |
michael@202 | 1969 | + NULL, NULL, 0, "Bridge/%s", chana->name))) { |
michael@202 | 1970 | + astman_send_error(s, m, "Unable to create temporary channel!"); |
michael@202 | 1971 | + return 1; |
michael@202 | 1972 | + } |
michael@202 | 1973 | + |
michael@202 | 1974 | + if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, |
michael@202 | 1975 | + NULL, NULL, 0, "Bridge/%s", chanb->name))) { |
michael@202 | 1976 | + astman_send_error(s, m, "Unable to create temporary channels!"); |
michael@202 | 1977 | + ast_channel_free(tmpchana); |
michael@202 | 1978 | + return 1; |
michael@202 | 1979 | + } |
michael@202 | 1980 | + |
michael@202 | 1981 | + do_bridge_masquerade(chana, tmpchana); |
michael@202 | 1982 | + do_bridge_masquerade(chanb, tmpchanb); |
michael@202 | 1983 | + |
michael@202 | 1984 | + /* make the channels compatible, send error if we fail doing so */ |
michael@202 | 1985 | + if (ast_channel_make_compatible(tmpchana, tmpchanb)) { |
michael@202 | 1986 | + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name); |
michael@202 | 1987 | + astman_send_error(s, m, "Could not make channels compatible for manager bridge"); |
michael@202 | 1988 | + ast_hangup(tmpchana); |
michael@202 | 1989 | + ast_hangup(tmpchanb); |
michael@202 | 1990 | + return 1; |
michael@202 | 1991 | + } |
michael@202 | 1992 | + |
michael@202 | 1993 | + /* setup the bridge thread object and start the bridge */ |
michael@202 | 1994 | + if (!(tobj = ast_calloc(1, sizeof(*tobj)))) { |
michael@202 | 1995 | + ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno)); |
michael@202 | 1996 | + astman_send_error(s, m, "Unable to spawn a new bridge thread"); |
michael@202 | 1997 | + ast_hangup(tmpchana); |
michael@202 | 1998 | + ast_hangup(tmpchanb); |
michael@202 | 1999 | + return 1; |
michael@202 | 2000 | + } |
michael@202 | 2001 | + |
michael@202 | 2002 | + tobj->chan = tmpchana; |
michael@202 | 2003 | + tobj->peer = tmpchanb; |
michael@202 | 2004 | + |
michael@202 | 2005 | + if (ast_true(playtone)) { |
michael@202 | 2006 | + if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) { |
michael@202 | 2007 | + if (ast_waitstream(tmpchanb, "") < 0) |
michael@202 | 2008 | + ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name); |
michael@202 | 2009 | + } |
michael@202 | 2010 | + } |
michael@202 | 2011 | + |
michael@202 | 2012 | + ast_bridge_call_thread_launch(tobj); |
michael@202 | 2013 | + |
michael@202 | 2014 | + astman_send_ack(s, m, "Launched bridge thread with success"); |
michael@202 | 2015 | + |
michael@202 | 2016 | + return 0; |
michael@202 | 2017 | +} |
michael@202 | 2018 | + |
michael@202 | 2019 | +static char *app_bridge = "Bridge"; |
michael@202 | 2020 | +static char *bridge_synopsis = "Bridge two channels"; |
michael@202 | 2021 | +static char *bridge_descrip = |
michael@202 | 2022 | +"Usage: Bridge(channel[,options])\n" |
michael@202 | 2023 | +" Allows the ability to bridge two channels via the dialplan.\n" |
michael@202 | 2024 | +"The current channel is bridged to the specified 'channel'.\n" |
michael@202 | 2025 | +" Options:\n" |
michael@202 | 2026 | +" p - Play a courtesy tone to 'channel'.\n" |
michael@202 | 2027 | +"This application sets the following channel variable upon completion:\n" |
michael@202 | 2028 | +" BRIDGERESULT The result of the bridge attempt as a text string, one of\n" |
michael@202 | 2029 | +" SUCCESS | FAILURE | LOOP | NONEXISTENT | INCOMPATIBLE\n"; |
michael@202 | 2030 | + |
michael@202 | 2031 | +enum { |
michael@202 | 2032 | + BRIDGE_OPT_PLAYTONE = (1 << 0), |
michael@202 | 2033 | +}; |
michael@202 | 2034 | + |
michael@202 | 2035 | +AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS |
michael@202 | 2036 | + AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE) |
michael@202 | 2037 | +END_OPTIONS ); |
michael@202 | 2038 | + |
michael@202 | 2039 | +/*! |
michael@202 | 2040 | + * \brief Bridge channels |
michael@202 | 2041 | + * \param chan |
michael@202 | 2042 | + * \param data channel to bridge with. |
michael@202 | 2043 | + * |
michael@202 | 2044 | + * Split data, check we aren't bridging with ourself, check valid channel, |
michael@202 | 2045 | + * answer call if not already, check compatible channels, setup bridge config |
michael@202 | 2046 | + * now bridge call, if transfered party hangs up return to PBX extension. |
michael@202 | 2047 | +*/ |
michael@202 | 2048 | +static int bridge_exec(struct ast_channel *chan, void *data) |
michael@202 | 2049 | +{ |
michael@202 | 2050 | + struct ast_channel *current_dest_chan, *final_dest_chan; |
michael@202 | 2051 | + char *tmp_data = NULL; |
michael@202 | 2052 | + struct ast_flags opts = { 0, }; |
michael@202 | 2053 | + struct ast_bridge_config bconfig = { { 0, }, }; |
michael@202 | 2054 | + |
michael@202 | 2055 | + AST_DECLARE_APP_ARGS(args, |
michael@202 | 2056 | + AST_APP_ARG(dest_chan); |
michael@202 | 2057 | + AST_APP_ARG(options); |
michael@202 | 2058 | + ); |
michael@202 | 2059 | + |
michael@202 | 2060 | + if (ast_strlen_zero(data)) { |
michael@202 | 2061 | + ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n"); |
michael@202 | 2062 | + return -1; |
michael@202 | 2063 | + } |
michael@202 | 2064 | + |
michael@202 | 2065 | + tmp_data = ast_strdupa(data); |
michael@202 | 2066 | + AST_STANDARD_APP_ARGS(args, tmp_data); |
michael@202 | 2067 | + if (!ast_strlen_zero(args.options)) |
michael@202 | 2068 | + ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options); |
michael@202 | 2069 | + |
michael@202 | 2070 | + /* avoid bridge with ourselves */ |
michael@202 | 2071 | + if (!strncmp(chan->name, args.dest_chan, |
michael@202 | 2072 | + strlen(chan->name) < strlen(args.dest_chan) ? |
michael@202 | 2073 | + strlen(chan->name) : strlen(args.dest_chan))) { |
michael@202 | 2074 | + ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name); |
michael@202 | 2075 | + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
michael@202 | 2076 | + "Response: Failed\r\n" |
michael@202 | 2077 | + "Reason: Unable to bridge channel to itself\r\n" |
michael@202 | 2078 | + "Channel1: %s\r\n" |
michael@202 | 2079 | + "Channel2: %s\r\n", |
michael@202 | 2080 | + chan->name, args.dest_chan); |
michael@202 | 2081 | + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP"); |
michael@202 | 2082 | + return 0; |
michael@202 | 2083 | + } |
michael@202 | 2084 | + |
michael@202 | 2085 | + /* make sure we have a valid end point */ |
michael@202 | 2086 | + if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan, |
michael@202 | 2087 | + strlen(args.dest_chan)))) { |
michael@202 | 2088 | + ast_log(LOG_WARNING, "Bridge failed because channel %s does not exist or we " |
michael@202 | 2089 | + "cannot get its lock\n", args.dest_chan); |
michael@202 | 2090 | + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
michael@202 | 2091 | + "Response: Failed\r\n" |
michael@202 | 2092 | + "Reason: Cannot grab end point\r\n" |
michael@202 | 2093 | + "Channel1: %s\r\n" |
michael@202 | 2094 | + "Channel2: %s\r\n", chan->name, args.dest_chan); |
michael@202 | 2095 | + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT"); |
michael@202 | 2096 | + return 0; |
michael@202 | 2097 | + } |
michael@202 | 2098 | + ast_channel_unlock(current_dest_chan); |
michael@202 | 2099 | + |
michael@202 | 2100 | + /* answer the channel if needed */ |
michael@202 | 2101 | + if (current_dest_chan->_state != AST_STATE_UP) |
michael@202 | 2102 | + ast_answer(current_dest_chan); |
michael@202 | 2103 | + |
michael@202 | 2104 | + /* try to allocate a place holder where current_dest_chan will be placed */ |
michael@202 | 2105 | + if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, |
michael@202 | 2106 | + NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) { |
michael@202 | 2107 | + ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan); |
michael@202 | 2108 | + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
michael@202 | 2109 | + "Response: Failed\r\n" |
michael@202 | 2110 | + "Reason: cannot create placeholder\r\n" |
michael@202 | 2111 | + "Channel1: %s\r\n" |
michael@202 | 2112 | + "Channel2: %s\r\n", chan->name, args.dest_chan); |
michael@202 | 2113 | + } |
michael@202 | 2114 | + do_bridge_masquerade(current_dest_chan, final_dest_chan); |
michael@202 | 2115 | + |
michael@202 | 2116 | + /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */ |
michael@202 | 2117 | + /* try to make compatible, send error if we fail */ |
michael@202 | 2118 | + if (ast_channel_make_compatible(chan, final_dest_chan) < 0) { |
michael@202 | 2119 | + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name); |
michael@202 | 2120 | + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
michael@202 | 2121 | + "Response: Failed\r\n" |
michael@202 | 2122 | + "Reason: Could not make channels compatible for bridge\r\n" |
michael@202 | 2123 | + "Channel1: %s\r\n" |
michael@202 | 2124 | + "Channel2: %s\r\n", chan->name, final_dest_chan->name); |
michael@202 | 2125 | + ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */ |
michael@202 | 2126 | + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE"); |
michael@202 | 2127 | + return 0; |
michael@202 | 2128 | + } |
michael@202 | 2129 | + |
michael@202 | 2130 | + /* Report that the bridge will be successfull */ |
michael@202 | 2131 | + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
michael@202 | 2132 | + "Response: Success\r\n" |
michael@202 | 2133 | + "Channel1: %s\r\n" |
michael@202 | 2134 | + "Channel2: %s\r\n", chan->name, final_dest_chan->name); |
michael@202 | 2135 | + |
michael@202 | 2136 | + /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */ |
michael@202 | 2137 | + if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) { |
michael@202 | 2138 | + if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) { |
michael@202 | 2139 | + if (ast_waitstream(final_dest_chan, "") < 0) |
michael@202 | 2140 | + ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name); |
michael@202 | 2141 | + } |
michael@202 | 2142 | + } |
michael@202 | 2143 | + |
michael@202 | 2144 | + /* do the bridge */ |
michael@202 | 2145 | + ast_bridge_call(chan, final_dest_chan, &bconfig); |
michael@202 | 2146 | + |
michael@202 | 2147 | + /* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */ |
michael@202 | 2148 | + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS"); |
michael@202 | 2149 | + if (!ast_check_hangup(final_dest_chan)) { |
michael@202 | 2150 | + ast_log(LOG_EVENT, "starting new PBX in %s,%s,%d for chan %s\n", |
michael@202 | 2151 | + final_dest_chan->context, final_dest_chan->exten, |
michael@202 | 2152 | + final_dest_chan->priority, final_dest_chan->name); |
michael@202 | 2153 | + |
michael@202 | 2154 | + if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) { |
michael@202 | 2155 | + ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name); |
michael@202 | 2156 | + ast_hangup(final_dest_chan); |
michael@202 | 2157 | + } else |
michael@202 | 2158 | + ast_log(LOG_EVENT, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name); |
michael@202 | 2159 | + } else { |
michael@202 | 2160 | + ast_log(LOG_EVENT, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name); |
michael@202 | 2161 | + ast_hangup(final_dest_chan); |
michael@202 | 2162 | + } |
michael@202 | 2163 | + |
michael@202 | 2164 | + return 0; |
michael@202 | 2165 | +} |
michael@202 | 2166 | |
michael@202 | 2167 | static int load_config(void) |
michael@202 | 2168 | { |
michael@202 | 2169 | @@ -3034,6 +3325,8 @@ |
michael@202 | 2170 | { |
michael@202 | 2171 | int res; |
michael@202 | 2172 | |
michael@202 | 2173 | + ast_register_application(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip); |
michael@202 | 2174 | + |
michael@202 | 2175 | memset(parking_ext, 0, sizeof(parking_ext)); |
michael@202 | 2176 | memset(parking_con, 0, sizeof(parking_con)); |
michael@202 | 2177 | |
michael@202 | 2178 | @@ -3048,6 +3341,7 @@ |
michael@202 | 2179 | ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" ); |
michael@202 | 2180 | ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park, |
michael@202 | 2181 | "Park a channel", mandescr_park); |
michael@202 | 2182 | + ast_manager_register2("Bridge", EVENT_FLAG_CALL, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge); |
michael@202 | 2183 | } |
michael@202 | 2184 | |
michael@202 | 2185 | res |= ast_devstate_prov_add("Park", metermaidstate); |
michael@202 | 2186 | Index: apps/app_voicemail.c |
michael@202 | 2187 | diff -Nau apps/app_voicemail.c.orig apps/app_voicemail.c |
michael@202 | 2188 | --- apps/app_voicemail.c.orig 2009-04-25 02:38:20.343758775 +0200 |
michael@202 | 2189 | +++ apps/app_voicemail.c 2009-04-25 19:56:25.287569363 +0200 |
michael@202 | 2190 | @@ -115,6 +115,7 @@ |
michael@202 | 2191 | static char imapport[8]; |
michael@202 | 2192 | static char imapflags[128]; |
michael@202 | 2193 | static char imapfolder[64]; |
michael@202 | 2194 | +static int imapsubfold = 0; |
michael@202 | 2195 | static char authuser[32]; |
michael@202 | 2196 | static char authpassword[42]; |
michael@202 | 2197 | |
michael@202 | 2198 | @@ -4313,6 +4314,7 @@ |
michael@202 | 2199 | /* we must use mbox(x) folder names, and copy the message there */ |
michael@202 | 2200 | /* simple. huh? */ |
michael@202 | 2201 | char sequence[10]; |
michael@202 | 2202 | + char folder[256]; |
michael@202 | 2203 | /* get the real IMAP message number for this message */ |
michael@202 | 2204 | snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]); |
michael@202 | 2205 | if (option_debug > 2) |
michael@202 | 2206 | @@ -4323,11 +4325,21 @@ |
michael@202 | 2207 | } else if (box == 0) { |
michael@202 | 2208 | mail_clearflag(vms->mailstream, sequence, "\\Seen"); |
michael@202 | 2209 | } |
michael@202 | 2210 | - if (!strcasecmp(mbox(0), vms->curbox) && (box == 0 || box == 1)) { |
michael@202 | 2211 | + if ((!strcasecmp(mbox(0), vms->curbox) || \ |
michael@202 | 2212 | + !strcasecmp(mbox(1), vms->curbox)) && \ |
michael@202 | 2213 | + (box == 0 || box == 1)) { /* Don't copy data, just change Seen flag */ |
michael@202 | 2214 | ast_mutex_unlock(&vms->lock); |
michael@202 | 2215 | return 0; |
michael@202 | 2216 | - } else { |
michael@202 | 2217 | - int res = !mail_copy(vms->mailstream,sequence,(char *) mbox(box)); |
michael@202 | 2218 | + } else if (box > 1) { /* Do copy data using INBOX or subfolder */ |
michael@202 | 2219 | + if (imapsubfold == 1) |
michael@202 | 2220 | + snprintf(folder, sizeof(folder), "%s%c%s", imapfolder, delimiter, mbox(box)); |
michael@202 | 2221 | + else |
michael@202 | 2222 | + strncpy(folder, mbox(box), sizeof(folder)); |
michael@202 | 2223 | + int res = !mail_copy(vms->mailstream,sequence,folder); |
michael@202 | 2224 | + ast_mutex_unlock(&vms->lock); |
michael@202 | 2225 | + return res; |
michael@202 | 2226 | + } else { /* Copy data to INBOX delegating new/old status to Seen flag */ |
michael@202 | 2227 | + int res = !mail_copy(vms->mailstream,sequence,imapfolder); |
michael@202 | 2228 | ast_mutex_unlock(&vms->lock); |
michael@202 | 2229 | return res; |
michael@202 | 2230 | } |
michael@202 | 2231 | @@ -7686,6 +7698,10 @@ |
michael@202 | 2232 | #ifndef IMAP_STORAGE |
michael@202 | 2233 | } else if (!cmd) { |
michael@202 | 2234 | vms.deleted[vms.curmsg] = 1; |
michael@202 | 2235 | +#else |
michael@202 | 2236 | + } else if (!cmd && (folder_int(vms.curbox) > 1 || box > 1)) { |
michael@202 | 2237 | + vms.deleted[vms.curmsg] = 1; /* Enforce deletion after */ |
michael@202 | 2238 | + deleted = 1; /* successful copy op */ |
michael@202 | 2239 | #endif |
michael@202 | 2240 | } else { |
michael@202 | 2241 | vms.deleted[vms.curmsg] = 0; |
michael@202 | 2242 | @@ -8198,6 +8214,7 @@ |
michael@202 | 2243 | const char *imap_port; |
michael@202 | 2244 | const char *imap_flags; |
michael@202 | 2245 | const char *imap_folder; |
michael@202 | 2246 | + const char *imap_use_subfold; |
michael@202 | 2247 | const char *auth_user; |
michael@202 | 2248 | const char *auth_password; |
michael@202 | 2249 | const char *expunge_on_hangup; |
michael@202 | 2250 | @@ -8342,6 +8359,15 @@ |
michael@202 | 2251 | } else { |
michael@202 | 2252 | ast_copy_string(imapfolder,"INBOX", sizeof(imapfolder)); |
michael@202 | 2253 | } |
michael@202 | 2254 | + /* IMAP saved (sub)folder location policy */ |
michael@202 | 2255 | + if ((imap_use_subfold = ast_variable_retrieve(cfg, "general", "imapsubfold"))) { |
michael@202 | 2256 | + if (ast_false(imap_use_subfold)) |
michael@202 | 2257 | + imapsubfold = 0; |
michael@202 | 2258 | + else |
michael@202 | 2259 | + imapsubfold = 1; |
michael@202 | 2260 | + } else { |
michael@202 | 2261 | + imapsubfold = 0; |
michael@202 | 2262 | + } |
michael@202 | 2263 | |
michael@202 | 2264 | /* There is some very unorthodox casting done here. This is due |
michael@202 | 2265 | * to the way c-client handles the argument passed in. It expects a |