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