00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdlib.h>
00026 #include <unistd.h>
00027 #include <string.h>
00028 #include <errno.h>
00029 #include <stdio.h>
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 47859 $")
00034
00035 #include "asterisk/lock.h"
00036 #include "asterisk/frame.h"
00037 #include "asterisk/logger.h"
00038 #include "asterisk/options.h"
00039 #include "asterisk/channel.h"
00040 #include "asterisk/cli.h"
00041 #include "asterisk/term.h"
00042 #include "asterisk/utils.h"
00043
00044 #ifdef TRACE_FRAMES
00045 static int headers = 0;
00046 static struct ast_frame *headerlist = NULL;
00047 AST_MUTEX_DEFINE_STATIC(framelock);
00048 #endif
00049
00050 #define SMOOTHER_SIZE 8000
00051
00052 #define TYPE_HIGH 0x0
00053 #define TYPE_LOW 0x1
00054 #define TYPE_SILENCE 0x2
00055 #define TYPE_DONTSEND 0x3
00056 #define TYPE_MASK 0x3
00057
00058 struct ast_format_list {
00059 int visible;
00060 int bits;
00061 char *name;
00062 char *desc;
00063 };
00064
00065 struct ast_smoother {
00066 int size;
00067 int format;
00068 int readdata;
00069 int optimizablestream;
00070 int flags;
00071 float samplesperbyte;
00072 struct ast_frame f;
00073 struct timeval delivery;
00074 char data[SMOOTHER_SIZE];
00075 char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
00076 struct ast_frame *opt;
00077 int len;
00078 };
00079
00080
00081 static struct ast_format_list AST_FORMAT_LIST[] = {
00082 { 1, AST_FORMAT_G723_1 , "g723" , "G.723.1"},
00083 { 1, AST_FORMAT_GSM, "gsm" , "GSM"},
00084 { 1, AST_FORMAT_ULAW, "ulaw", "G.711 u-law" },
00085 { 1, AST_FORMAT_ALAW, "alaw", "G.711 A-law" },
00086 { 1, AST_FORMAT_G726, "g726", "G.726" },
00087 { 1, AST_FORMAT_ADPCM, "adpcm" , "ADPCM"},
00088 { 1, AST_FORMAT_SLINEAR, "slin", "16 bit Signed Linear PCM"},
00089 { 1, AST_FORMAT_LPC10, "lpc10", "LPC10" },
00090 { 1, AST_FORMAT_G729A, "g729", "G.729A" },
00091 { 1, AST_FORMAT_SPEEX, "speex", "SpeeX" },
00092 { 1, AST_FORMAT_ILBC, "ilbc", "iLBC"},
00093 { 0, 0, "nothing", "undefined" },
00094 { 0, 0, "nothing", "undefined" },
00095 { 0, 0, "nothing", "undefined" },
00096 { 0, 0, "nothing", "undefined" },
00097 { 0, AST_FORMAT_MAX_AUDIO, "maxaudio", "Maximum audio format" },
00098 { 1, AST_FORMAT_JPEG, "jpeg", "JPEG image"},
00099 { 1, AST_FORMAT_PNG, "png", "PNG image"},
00100 { 1, AST_FORMAT_H261, "h261", "H.261 Video" },
00101 { 1, AST_FORMAT_H263, "h263", "H.263 Video" },
00102 { 1, AST_FORMAT_H263_PLUS, "h263p", "H.263+ Video" },
00103 { 0, 0, "nothing", "undefined" },
00104 { 0, 0, "nothing", "undefined" },
00105 { 0, 0, "nothing", "undefined" },
00106 { 0, 0, "nothing", "undefined" },
00107 { 0, AST_FORMAT_MAX_VIDEO, "maxvideo", "Maximum video format" },
00108 };
00109
00110 void ast_smoother_reset(struct ast_smoother *s, int size)
00111 {
00112 memset(s, 0, sizeof(struct ast_smoother));
00113 s->size = size;
00114 }
00115
00116 struct ast_smoother *ast_smoother_new(int size)
00117 {
00118 struct ast_smoother *s;
00119 if (size < 1)
00120 return NULL;
00121 s = malloc(sizeof(struct ast_smoother));
00122 if (s)
00123 ast_smoother_reset(s, size);
00124 return s;
00125 }
00126
00127 int ast_smoother_get_flags(struct ast_smoother *s)
00128 {
00129 return s->flags;
00130 }
00131
00132 void ast_smoother_set_flags(struct ast_smoother *s, int flags)
00133 {
00134 s->flags = flags;
00135 }
00136
00137 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
00138 {
00139 if (f->frametype != AST_FRAME_VOICE) {
00140 ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
00141 return -1;
00142 }
00143 if (!s->format) {
00144 s->format = f->subclass;
00145 s->samplesperbyte = (float)f->samples / (float)f->datalen;
00146 } else if (s->format != f->subclass) {
00147 ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
00148 return -1;
00149 }
00150 if (s->len + f->datalen > SMOOTHER_SIZE) {
00151 ast_log(LOG_WARNING, "Out of smoother space\n");
00152 return -1;
00153 }
00154 if (((f->datalen == s->size) || ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729)))
00155 && !s->opt && (f->offset >= AST_MIN_OFFSET)) {
00156 if (!s->len) {
00157
00158
00159
00160 if (swap)
00161 ast_swapcopy_samples(f->data, f->data, f->samples);
00162 s->opt = f;
00163 return 0;
00164 } else {
00165 s->optimizablestream++;
00166 if (s->optimizablestream > 10) {
00167
00168
00169
00170
00171
00172 if (swap)
00173 ast_swapcopy_samples(f->data, f->data, f->samples);
00174 s->len = 0;
00175 s->opt = f;
00176 return 0;
00177 }
00178 }
00179 } else
00180 s->optimizablestream = 0;
00181 if (s->flags & AST_SMOOTHER_FLAG_G729) {
00182 if (s->len % 10) {
00183 ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
00184 return 0;
00185 }
00186 }
00187 if (swap)
00188 ast_swapcopy_samples(s->data+s->len, f->data, f->samples);
00189 else
00190 memcpy(s->data + s->len, f->data, f->datalen);
00191
00192 if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery))
00193 s->delivery = f->delivery;
00194 s->len += f->datalen;
00195 return 0;
00196 }
00197
00198 struct ast_frame *ast_smoother_read(struct ast_smoother *s)
00199 {
00200 struct ast_frame *opt;
00201 int len;
00202
00203 if (s->opt) {
00204 if (s->opt->offset < AST_FRIENDLY_OFFSET)
00205 ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
00206 s->opt->offset);
00207 opt = s->opt;
00208 s->opt = NULL;
00209 return opt;
00210 }
00211
00212
00213 if (s->len < s->size) {
00214
00215 if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->size % 10)))
00216 return NULL;
00217 }
00218 len = s->size;
00219 if (len > s->len)
00220 len = s->len;
00221
00222 s->f.frametype = AST_FRAME_VOICE;
00223 s->f.subclass = s->format;
00224 s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
00225 s->f.offset = AST_FRIENDLY_OFFSET;
00226 s->f.datalen = len;
00227
00228 s->f.samples = len * s->samplesperbyte;
00229 s->f.delivery = s->delivery;
00230
00231 memcpy(s->f.data, s->data, len);
00232 s->len -= len;
00233
00234 if (s->len) {
00235
00236
00237 memmove(s->data, s->data + len, s->len);
00238 if (!ast_tvzero(s->delivery)) {
00239
00240 s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, 8000));
00241 }
00242 }
00243
00244 return &s->f;
00245 }
00246
00247 void ast_smoother_free(struct ast_smoother *s)
00248 {
00249 free(s);
00250 }
00251
00252 static struct ast_frame *ast_frame_header_new(void)
00253 {
00254 struct ast_frame *f;
00255 f = malloc(sizeof(struct ast_frame));
00256 if (f)
00257 memset(f, 0, sizeof(struct ast_frame));
00258 #ifdef TRACE_FRAMES
00259 if (f) {
00260 f->prev = NULL;
00261 ast_mutex_lock(&framelock);
00262 headers++;
00263 f->next = headerlist;
00264 if (headerlist)
00265 headerlist->prev = f;
00266 headerlist = f;
00267 ast_mutex_unlock(&framelock);
00268 }
00269 #endif
00270 return f;
00271 }
00272
00273
00274
00275
00276
00277 void ast_frfree(struct ast_frame *fr)
00278 {
00279 if (fr->mallocd & AST_MALLOCD_DATA) {
00280 if (fr->data)
00281 free(fr->data - fr->offset);
00282 }
00283 if (fr->mallocd & AST_MALLOCD_SRC) {
00284 if (fr->src)
00285 free((char *)fr->src);
00286 }
00287 if (fr->mallocd & AST_MALLOCD_HDR) {
00288 #ifdef TRACE_FRAMES
00289 ast_mutex_lock(&framelock);
00290 headers--;
00291 if (fr->next)
00292 fr->next->prev = fr->prev;
00293 if (fr->prev)
00294 fr->prev->next = fr->next;
00295 else
00296 headerlist = fr->next;
00297 ast_mutex_unlock(&framelock);
00298 #endif
00299 free(fr);
00300 }
00301 }
00302
00303
00304
00305
00306
00307
00308 struct ast_frame *ast_frisolate(struct ast_frame *fr)
00309 {
00310 struct ast_frame *out;
00311 void *newdata;
00312
00313 if (!(fr->mallocd & AST_MALLOCD_HDR)) {
00314
00315 out = ast_frame_header_new();
00316 if (!out) {
00317 ast_log(LOG_WARNING, "Out of memory\n");
00318 return NULL;
00319 }
00320 out->frametype = fr->frametype;
00321 out->subclass = fr->subclass;
00322 out->datalen = fr->datalen;
00323 out->samples = fr->samples;
00324 out->offset = fr->offset;
00325 out->src = NULL;
00326 out->data = fr->data;
00327 } else
00328 out = fr;
00329
00330 if (!(fr->mallocd & AST_MALLOCD_SRC)) {
00331 if (fr->src) {
00332 out->src = strdup(fr->src);
00333 if (!out->src) {
00334 if (out != fr)
00335 free(out);
00336 ast_log(LOG_WARNING, "Out of memory\n");
00337 return NULL;
00338 }
00339 }
00340 } else
00341 out->src = fr->src;
00342
00343 if (!(fr->mallocd & AST_MALLOCD_DATA)) {
00344 newdata = malloc(fr->datalen + AST_FRIENDLY_OFFSET);
00345 if (!newdata) {
00346 if (out->src != fr->src)
00347 free((void *) out->src);
00348 if (out != fr)
00349 free(out);
00350 ast_log(LOG_WARNING, "Out of memory\n");
00351 return NULL;
00352 }
00353 newdata += AST_FRIENDLY_OFFSET;
00354 out->offset = AST_FRIENDLY_OFFSET;
00355 out->datalen = fr->datalen;
00356 memcpy(newdata, fr->data, fr->datalen);
00357 out->data = newdata;
00358 }
00359
00360 out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
00361
00362 return out;
00363 }
00364
00365 struct ast_frame *ast_frdup(struct ast_frame *f)
00366 {
00367 struct ast_frame *out;
00368 int len, srclen = 0;
00369 void *buf;
00370
00371 len = sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET + f->datalen;
00372
00373
00374
00375
00376
00377 if (f->src)
00378 srclen = strlen(f->src);
00379 if (srclen > 0)
00380 len += srclen + 1;
00381 buf = calloc(1, len);
00382 if (!buf)
00383 return NULL;
00384 out = buf;
00385
00386
00387 out->frametype = f->frametype;
00388 out->subclass = f->subclass;
00389 out->datalen = f->datalen;
00390 out->samples = f->samples;
00391 out->delivery = f->delivery;
00392 out->mallocd = AST_MALLOCD_HDR;
00393 out->offset = AST_FRIENDLY_OFFSET;
00394 if (out->datalen) {
00395 out->data = buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET;
00396 memcpy(out->data, f->data, out->datalen);
00397 }
00398 if (srclen > 0) {
00399 out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
00400
00401 strcpy((char *)out->src, f->src);
00402 }
00403 return out;
00404 }
00405
00406 #if 0
00407
00408
00409
00410
00411
00412
00413 struct ast_frame *ast_fr_fdread(int fd)
00414 {
00415 char buf[65536];
00416 int res;
00417 int ttl = sizeof(struct ast_frame);
00418 struct ast_frame *f = (struct ast_frame *)buf;
00419
00420
00421
00422 while(ttl) {
00423 res = read(fd, buf, ttl);
00424 if (res < 0) {
00425 ast_log(LOG_WARNING, "Bad read on %d: %s\n", fd, strerror(errno));
00426 return NULL;
00427 }
00428 ttl -= res;
00429 }
00430
00431
00432 f->mallocd = 0;
00433
00434 f->data = buf + sizeof(struct ast_frame);
00435 f->offset = 0;
00436
00437 f->mallocd = 0;
00438
00439 f->src = (char *)__FUNCTION__;
00440 if (f->datalen > sizeof(buf) - sizeof(struct ast_frame)) {
00441
00442 ast_log(LOG_WARNING, "Strange read (%d bytes)\n", f->datalen);
00443 return NULL;
00444 }
00445 if (f->datalen) {
00446 if ((res = read(fd, f->data, f->datalen)) != f->datalen) {
00447
00448 ast_log(LOG_WARNING, "How very strange, expected %d, got %d\n", f->datalen, res);
00449 return NULL;
00450 }
00451 }
00452 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
00453 return NULL;
00454 }
00455 return ast_frisolate(f);
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 int ast_fr_fdwrite(int fd, struct ast_frame *frame)
00467 {
00468
00469 if (write(fd, frame, sizeof(struct ast_frame)) != sizeof(struct ast_frame)) {
00470 ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
00471 return -1;
00472 }
00473 if (write(fd, frame->data, frame->datalen) != frame->datalen) {
00474 ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
00475 return -1;
00476 }
00477 return 0;
00478 }
00479
00480 int ast_fr_fdhangup(int fd)
00481 {
00482 struct ast_frame hangup = {
00483 AST_FRAME_CONTROL,
00484 AST_CONTROL_HANGUP
00485 };
00486 return ast_fr_fdwrite(fd, &hangup);
00487 }
00488
00489 #endif
00490 void ast_swapcopy_samples(void *dst, const void *src, int samples)
00491 {
00492 int i;
00493 unsigned short *dst_s = dst;
00494 const unsigned short *src_s = src;
00495
00496 for (i=0; i<samples; i++)
00497 dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
00498 }
00499
00500
00501 struct ast_format_list *ast_get_format_list_index(int index)
00502 {
00503 return &AST_FORMAT_LIST[index];
00504 }
00505
00506 struct ast_format_list *ast_get_format_list(size_t *size)
00507 {
00508 *size = (sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list));
00509 return AST_FORMAT_LIST;
00510 }
00511
00512 char* ast_getformatname(int format)
00513 {
00514 int x = 0;
00515 char *ret = "unknown";
00516 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00517 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == format) {
00518 ret = AST_FORMAT_LIST[x].name;
00519 break;
00520 }
00521 }
00522 return ret;
00523 }
00524
00525 char *ast_getformatname_multiple(char *buf, size_t size, int format) {
00526
00527 int x = 0;
00528 unsigned len;
00529 char *end = buf;
00530 char *start = buf;
00531 if (!size) return buf;
00532 snprintf(end, size, "0x%x (", format);
00533 len = strlen(end);
00534 end += len;
00535 size -= len;
00536 start = end;
00537 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00538 if (AST_FORMAT_LIST[x].visible && (AST_FORMAT_LIST[x].bits & format)) {
00539 snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
00540 len = strlen(end);
00541 end += len;
00542 size -= len;
00543 }
00544 }
00545 if (start == end)
00546 snprintf(start, size, "nothing)");
00547 else if (size > 1)
00548 *(end -1) = ')';
00549 return buf;
00550 }
00551
00552 static struct ast_codec_alias_table {
00553 char *alias;
00554 char *realname;
00555
00556 } ast_codec_alias_table[] = {
00557 {"slinear","slin"},
00558 {"g723.1","g723"},
00559 };
00560
00561 static char *ast_expand_codec_alias(char *in) {
00562 int x = 0;
00563
00564 for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(struct ast_codec_alias_table) ; x++) {
00565 if(!strcmp(in,ast_codec_alias_table[x].alias))
00566 return ast_codec_alias_table[x].realname;
00567 }
00568 return in;
00569 }
00570
00571 int ast_getformatbyname(char *name)
00572 {
00573 int x = 0, all = 0, format = 0;
00574
00575 all = strcasecmp(name, "all") ? 0 : 1;
00576 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00577 if(AST_FORMAT_LIST[x].visible && (all ||
00578 !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
00579 !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name)))) {
00580 format |= AST_FORMAT_LIST[x].bits;
00581 if(!all)
00582 break;
00583 }
00584 }
00585
00586 return format;
00587 }
00588
00589 char *ast_codec2str(int codec) {
00590 int x = 0;
00591 char *ret = "unknown";
00592 for (x = 0 ; x < sizeof(AST_FORMAT_LIST) / sizeof(struct ast_format_list) ; x++) {
00593 if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == codec) {
00594 ret = AST_FORMAT_LIST[x].desc;
00595 break;
00596 }
00597 }
00598 return ret;
00599 }
00600
00601 static int show_codecs(int fd, int argc, char *argv[])
00602 {
00603 int i, found=0;
00604 char hex[25];
00605
00606 if ((argc < 2) || (argc > 3))
00607 return RESULT_SHOWUSAGE;
00608
00609 if (!option_dontwarn)
00610 ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
00611 "\tIt does not indicate anything about your configuration.\n");
00612
00613 ast_cli(fd, "%11s %9s %10s TYPE %5s %s\n","INT","BINARY","HEX","NAME","DESC");
00614 ast_cli(fd, "--------------------------------------------------------------------------------\n");
00615 if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
00616 found = 1;
00617 for (i=0;i<11;i++) {
00618 snprintf(hex,25,"(0x%x)",1<<i);
00619 ast_cli(fd, "%11u (1 << %2d) %10s audio %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00620 }
00621 }
00622
00623 if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
00624 found = 1;
00625 for (i=16;i<18;i++) {
00626 snprintf(hex,25,"(0x%x)",1<<i);
00627 ast_cli(fd, "%11u (1 << %2d) %10s image %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00628 }
00629 }
00630
00631 if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
00632 found = 1;
00633 for (i=18;i<21;i++) {
00634 snprintf(hex,25,"(0x%x)",1<<i);
00635 ast_cli(fd, "%11u (1 << %2d) %10s video %5s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
00636 }
00637 }
00638
00639 if (! found)
00640 return RESULT_SHOWUSAGE;
00641 else
00642 return RESULT_SUCCESS;
00643 }
00644
00645 static char frame_show_codecs_usage[] =
00646 "Usage: show [audio|video|image] codecs\n"
00647 " Displays codec mapping\n";
00648
00649 static int show_codec_n(int fd, int argc, char *argv[])
00650 {
00651 int codec, i, found=0;
00652
00653 if (argc != 3)
00654 return RESULT_SHOWUSAGE;
00655
00656 if (sscanf(argv[2],"%d",&codec) != 1)
00657 return RESULT_SHOWUSAGE;
00658
00659 for (i=0;i<32;i++)
00660 if (codec & (1 << i)) {
00661 found = 1;
00662 ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
00663 }
00664
00665 if (! found)
00666 ast_cli(fd, "Codec %d not found\n", codec);
00667
00668 return RESULT_SUCCESS;
00669 }
00670
00671 static char frame_show_codec_n_usage[] =
00672 "Usage: show codec <number>\n"
00673 " Displays codec mapping\n";
00674
00675
00676 void ast_frame_dump(char *name, struct ast_frame *f, char *prefix)
00677 {
00678 char *n = "unknown";
00679 char ftype[40] = "Unknown Frametype";
00680 char cft[80];
00681 char subclass[40] = "Unknown Subclass";
00682 char csub[80];
00683 char moreinfo[40] = "";
00684 char cn[60];
00685 char cp[40];
00686 char cmn[40];
00687 if (name)
00688 n = name;
00689 if (!f) {
00690 ast_verbose("%s [ %s (NULL) ] [%s]\n",
00691 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00692 term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00693 term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00694 return;
00695 }
00696
00697 if (f->frametype == AST_FRAME_VOICE)
00698 return;
00699 if (f->frametype == AST_FRAME_VIDEO)
00700 return;
00701 switch(f->frametype) {
00702 case AST_FRAME_DTMF:
00703 strcpy(ftype, "DTMF");
00704 subclass[0] = f->subclass;
00705 subclass[1] = '\0';
00706 break;
00707 case AST_FRAME_CONTROL:
00708 strcpy(ftype, "Control");
00709 switch(f->subclass) {
00710 case AST_CONTROL_HANGUP:
00711 strcpy(subclass, "Hangup");
00712 break;
00713 case AST_CONTROL_RING:
00714 strcpy(subclass, "Ring");
00715 break;
00716 case AST_CONTROL_RINGING:
00717 strcpy(subclass, "Ringing");
00718 break;
00719 case AST_CONTROL_ANSWER:
00720 strcpy(subclass, "Answer");
00721 break;
00722 case AST_CONTROL_BUSY:
00723 strcpy(subclass, "Busy");
00724 break;
00725 case AST_CONTROL_TAKEOFFHOOK:
00726 strcpy(subclass, "Take Off Hook");
00727 break;
00728 case AST_CONTROL_OFFHOOK:
00729 strcpy(subclass, "Line Off Hook");
00730 break;
00731 case AST_CONTROL_CONGESTION:
00732 strcpy(subclass, "Congestion");
00733 break;
00734 case AST_CONTROL_FLASH:
00735 strcpy(subclass, "Flash");
00736 break;
00737 case AST_CONTROL_WINK:
00738 strcpy(subclass, "Wink");
00739 break;
00740 case AST_CONTROL_OPTION:
00741 strcpy(subclass, "Option");
00742 break;
00743 case AST_CONTROL_RADIO_KEY:
00744 strcpy(subclass, "Key Radio");
00745 break;
00746 case AST_CONTROL_RADIO_UNKEY:
00747 strcpy(subclass, "Unkey Radio");
00748 break;
00749 case -1:
00750 strcpy(subclass, "Stop generators");
00751 break;
00752 default:
00753 snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
00754 }
00755 break;
00756 case AST_FRAME_NULL:
00757 strcpy(ftype, "Null Frame");
00758 strcpy(subclass, "N/A");
00759 break;
00760 case AST_FRAME_IAX:
00761
00762 strcpy(ftype, "IAX Specific");
00763 snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
00764 break;
00765 case AST_FRAME_TEXT:
00766 strcpy(ftype, "Text");
00767 strcpy(subclass, "N/A");
00768 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
00769 break;
00770 case AST_FRAME_IMAGE:
00771 strcpy(ftype, "Image");
00772 snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
00773 break;
00774 case AST_FRAME_HTML:
00775 strcpy(ftype, "HTML");
00776 switch(f->subclass) {
00777 case AST_HTML_URL:
00778 strcpy(subclass, "URL");
00779 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
00780 break;
00781 case AST_HTML_DATA:
00782 strcpy(subclass, "Data");
00783 break;
00784 case AST_HTML_BEGIN:
00785 strcpy(subclass, "Begin");
00786 break;
00787 case AST_HTML_END:
00788 strcpy(subclass, "End");
00789 break;
00790 case AST_HTML_LDCOMPLETE:
00791 strcpy(subclass, "Load Complete");
00792 break;
00793 case AST_HTML_NOSUPPORT:
00794 strcpy(subclass, "No Support");
00795 break;
00796 case AST_HTML_LINKURL:
00797 strcpy(subclass, "Link URL");
00798 ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
00799 break;
00800 case AST_HTML_UNLINK:
00801 strcpy(subclass, "Unlink");
00802 break;
00803 case AST_HTML_LINKREJECT:
00804 strcpy(subclass, "Link Reject");
00805 break;
00806 default:
00807 snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
00808 break;
00809 }
00810 break;
00811 default:
00812 snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
00813 }
00814 if (!ast_strlen_zero(moreinfo))
00815 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
00816 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00817 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00818 f->frametype,
00819 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00820 f->subclass,
00821 term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
00822 term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00823 else
00824 ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
00825 term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00826 term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00827 f->frametype,
00828 term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00829 f->subclass,
00830 term_color(cn, n, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00831
00832 }
00833
00834
00835 #ifdef TRACE_FRAMES
00836 static int show_frame_stats(int fd, int argc, char *argv[])
00837 {
00838 struct ast_frame *f;
00839 int x=1;
00840 if (argc != 3)
00841 return RESULT_SHOWUSAGE;
00842 ast_mutex_lock(&framelock);
00843 ast_cli(fd, " Framer Statistics \n");
00844 ast_cli(fd, "---------------------------\n");
00845 ast_cli(fd, "Total allocated headers: %d\n", headers);
00846 ast_cli(fd, "Queue Dump:\n");
00847 for (f=headerlist; f; f = f->next) {
00848 ast_cli(fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
00849 }
00850 ast_mutex_unlock(&framelock);
00851 return RESULT_SUCCESS;
00852 }
00853
00854 static char frame_stats_usage[] =
00855 "Usage: show frame stats\n"
00856 " Displays debugging statistics from framer\n";
00857 #endif
00858
00859
00860 static struct ast_cli_entry my_clis[] = {
00861 { { "show", "codecs", NULL }, show_codecs, "Shows codecs", frame_show_codecs_usage },
00862 { { "show", "audio", "codecs", NULL }, show_codecs, "Shows audio codecs", frame_show_codecs_usage },
00863 { { "show", "video", "codecs", NULL }, show_codecs, "Shows video codecs", frame_show_codecs_usage },
00864 { { "show", "image", "codecs", NULL }, show_codecs, "Shows image codecs", frame_show_codecs_usage },
00865 { { "show", "codec", NULL }, show_codec_n, "Shows a specific codec", frame_show_codec_n_usage },
00866 #ifdef TRACE_FRAMES
00867 { { "show", "frame", "stats", NULL }, show_frame_stats, "Shows frame statistics", frame_stats_usage },
00868 #endif
00869 };
00870
00871 int init_framer(void)
00872 {
00873 ast_cli_register_multiple(my_clis, sizeof(my_clis)/sizeof(my_clis[0]) );
00874 return 0;
00875 }
00876
00877 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
00878 {
00879 int x = 0, differential = (int) 'A', mem = 0;
00880 char *from = NULL, *to = NULL;
00881
00882 if(right) {
00883 from = pref->order;
00884 to = buf;
00885 mem = size;
00886 } else {
00887 to = pref->order;
00888 from = buf;
00889 mem = 32;
00890 }
00891
00892 memset(to, 0, mem);
00893 for (x = 0; x < 32 ; x++) {
00894 if(!from[x])
00895 break;
00896 to[x] = right ? (from[x] + differential) : (from[x] - differential);
00897 }
00898 }
00899
00900 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
00901 {
00902 int x = 0, codec = 0;
00903 size_t total_len = 0, slen = 0;
00904 char *formatname = 0;
00905
00906 memset(buf,0,size);
00907 total_len = size;
00908 buf[0] = '(';
00909 total_len--;
00910 for(x = 0; x < 32 ; x++) {
00911 if(total_len <= 0)
00912 break;
00913 if(!(codec = ast_codec_pref_index(pref,x)))
00914 break;
00915 if((formatname = ast_getformatname(codec))) {
00916 slen = strlen(formatname);
00917 if(slen > total_len)
00918 break;
00919 strncat(buf,formatname,total_len);
00920 total_len -= slen;
00921 }
00922 if(total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
00923 strncat(buf,