From e03ed12e000869b70150bce1491a452335e04470 Mon Sep 17 00:00:00 2001 From: Anthony Minessale II Date: Thu, 31 Mar 2005 18:00:35 +0000 Subject: minor tweak and optimization for chanspy git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5317 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_chanspy.c | 240 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 142 insertions(+), 98 deletions(-) diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index 4561d988d..065578e73 100755 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -31,13 +31,11 @@ AST_MUTEX_DEFINE_STATIC(modlock); #define ast_fit_in_short(in) (in < -32768 ? -32768 : in > 32767 ? 32767 : in) -#define find_smallest_of_three(a, b, c) ((a < b && a < c) ? a : (b < a && b < c) ? b : c) #define AST_NAME_STRLEN 256 #define ALL_DONE(u, ret) LOCAL_USER_REMOVE(u); return ret; #define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0 #define minmax(x,y) x ? (x > y) ? y : ((x < (y * -1)) ? (y * -1) : x) : 0 -#define CS_BUFLEN 640 - +#define CS_BUFLEN 1024 static char *synopsis = "Tap into any type of asterisk channel and listen to audio"; static char *app = "ChanSpy"; @@ -69,14 +67,28 @@ AST_DECLARE_OPTIONS(chanspy_opts,{ }); STANDARD_LOCAL_USER; - LOCAL_USER_DECL; struct chanspy_translation_helper { + /* spy data */ + struct ast_channel_spy spy; + + /* read frame */ + int fmt0; + short buf0[CS_BUFLEN]; struct ast_trans_pvt *trans0; + + /* write frame */ + int fmt1; struct ast_trans_pvt *trans1; + short buf1[CS_BUFLEN]; + + /* muxed frame */ + struct ast_frame frame; + short buf[CS_BUFLEN]; + int volfactor; - struct ast_channel_spy *spy; + }; /* Prototypes */ @@ -192,95 +204,122 @@ static void ast_flush_spy_queue(struct ast_channel_spy *spy) static int spy_generate(struct ast_channel *chan, void *data, int len, int samples) { - struct ast_frame *f0, *f1, write_frame, *f; - int x=0, framelen_a = 0, framelen_b = 0, size = 0; - short buf[CS_BUFLEN], buf0[CS_BUFLEN], buf1[CS_BUFLEN]; + struct ast_frame *f, *f0, *f1; + int x = 0, vf = 0; + struct chanspy_translation_helper *csth = data; - int nc = 0, vf; + + ast_mutex_lock(&csth->spy.lock); + f0 = spy_queue_shift(&csth->spy, 0); + f1 = spy_queue_shift(&csth->spy, 1); + ast_mutex_unlock(&csth->spy.lock); - ast_mutex_lock(&csth->spy->lock); - f0 = spy_queue_shift(csth->spy, 0); - f1 = spy_queue_shift(csth->spy, 1); - ast_mutex_unlock(&csth->spy->lock); - - if (f0 && f1) { - if (!csth->trans0) { - if (f0->subclass != AST_FORMAT_SLINEAR && (csth->trans0 = ast_translator_build_path(AST_FORMAT_SLINEAR, f0->subclass)) == NULL) { - ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(f0->subclass)); - return -1; - } - if (!csth->trans1) { - if (f1->subclass == f0->subclass) { - csth->trans1 = csth->trans0; - } else if (f1->subclass != AST_FORMAT_SLINEAR && (csth->trans1 = ast_translator_build_path(AST_FORMAT_SLINEAR, f1->subclass)) == NULL) { - ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(f1->subclass)); - return -1; - } - - } - } + if (!f0 && !f1) { + return 0; + } + + if (f0 && csth->fmt0 && csth->fmt0 != f0->subclass) { + ast_translator_free_path(csth->trans0); + csth->trans0 = NULL; + csth->fmt0 = csth->fmt0; + } + + if (f1 && csth->fmt1 && csth->fmt1 != f1->subclass) { + ast_translator_free_path(csth->trans1); + csth->trans1 = NULL; + csth->fmt1 = csth->fmt1; + } + + if (!csth->fmt0 && f0) { + csth->fmt0 = f0->subclass; + } - memset(buf, 0, sizeof(buf)); - memset(buf0, 0, sizeof(buf0)); - memset(buf1, 0, sizeof(buf1)); + if (!csth->fmt1 && f1) { + csth->fmt1 = f1->subclass; + } + + if (csth->fmt0 && csth->fmt0 != AST_FORMAT_SLINEAR && !csth->trans0) { + if (csth->fmt0 == csth->fmt1 && csth->trans1) { + csth->trans0 = csth->trans1; + } else if ((csth->trans0 = ast_translator_build_path(AST_FORMAT_SLINEAR, csth->fmt0)) == NULL) { + ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(csth->fmt0)); + return -1; + } + } + + if (csth->fmt1 && csth->fmt1 != AST_FORMAT_SLINEAR && !csth->trans1) { + if (csth->fmt1 == csth->fmt0 && csth->trans0) { + csth->trans1 = csth->trans0; + } else if ((csth->trans1 = ast_translator_build_path(AST_FORMAT_SLINEAR, csth->fmt1)) == NULL) { + ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(csth->fmt1)); + return -1; + } + } + + if (f0) { if (csth->trans0) { if ((f = ast_translate(csth->trans0, f0, 0))) { - framelen_a = f->datalen * sizeof(short); - memcpy(buf0, f->data, framelen_a); + memcpy(csth->buf0, f->data, f->datalen * sizeof(short)); ast_frfree(f); - } else + } else { return 0; + } } else { - framelen_a = f0->datalen * sizeof(short); - memcpy(buf0, f0->data, framelen_a); + memcpy(csth->buf0, f0->data, f0->datalen * sizeof(short)); } + } + + if (f1) { if (csth->trans1) { if ((f = ast_translate(csth->trans1, f1, 0))) { - framelen_b = f->datalen * sizeof(short); - memcpy(buf1, f->data, framelen_b); + memcpy(csth->buf1, f->data, f->datalen * sizeof(short)); ast_frfree(f); - } else + } else { return 0; + } } else { - framelen_b = f1->datalen * sizeof(short); - memcpy(buf1, f1->data, framelen_b); + memcpy(csth->buf1, f1->data, f1->datalen * sizeof(short)); } - size = find_smallest_of_three(len, framelen_a, framelen_b); - - vf = get_volfactor(csth->volfactor); - vf = minmax(vf, 16); - for(x=0; x < size; x++) { - if (vf < 0) { - buf0[x] /= abs(vf); - buf1[x] /= abs(vf); - } else if (vf > 0) { - buf0[x] *= vf; - buf1[x] *= vf; + } + + vf = get_volfactor(csth->volfactor); + vf = minmax(vf, 16); + for(x=0; x < len; x++) { + if (vf < 0) { + if (f0) { + csth->buf0[x] /= abs(vf); + } + if (f1) { + csth->buf1[x] /= abs(vf); + } + } else if (vf > 0) { + if (f0) { + csth->buf0[x] *= vf; + } + if (f1) { + csth->buf1[x] *= vf; } - buf[x] = ast_fit_in_short(buf0[x] + buf1[x]); } - memset(&write_frame, 0, sizeof(write_frame)); - write_frame.frametype = AST_FRAME_VOICE; - write_frame.subclass = AST_FORMAT_SLINEAR; - write_frame.datalen = size; - write_frame.samples = size; - write_frame.data = buf; - write_frame.offset = 0; - ast_write(chan, &write_frame); - } else { - nc++; - if(nc > 1) { - return -1; + if (f0 && f1) { + csth->buf[x] = ast_fit_in_short(csth->buf0[x] + csth->buf1[x]); + } else if (f0) { + csth->buf[x] = csth->buf0[x]; + } else if (f1) { + csth->buf[x] = csth->buf1[x]; } } + + csth->frame.data = csth->buf; + ast_write(chan, &csth->frame); - if (f0) + if (f0) { ast_frfree(f0); - if (f1) + } + if (f1) { ast_frfree(f1); + } return 0; - } static struct ast_generator spygen = { @@ -356,25 +395,25 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int int running = 1, res = 0, x = 0; char inp[24]; char *name=NULL; - struct ast_channel_spy spy; if (chan && !ast_check_hangup(chan) && spyee && !ast_check_hangup(spyee)) { memset(inp, 0, sizeof(inp)); name = ast_strdupa(spyee->name); if (option_verbose >= 2) ast_verbose(VERBOSE_PREFIX_2 "Spying on channel %s\n", name); - - memset(&spy, 0, sizeof(struct ast_channel_spy)); - spy.status = CHANSPY_RUNNING; - ast_mutex_init(&spy.lock); - start_spying(spyee, chan, &spy); - + memset(&csth, 0, sizeof(csth)); + csth.spy.status = CHANSPY_RUNNING; + ast_mutex_init(&csth.spy.lock); csth.volfactor = *volfactor; - csth.spy = &spy; + csth.frame.frametype = AST_FRAME_VOICE; + csth.frame.subclass = AST_FORMAT_SLINEAR; + csth.frame.datalen = 320; + csth.frame.samples = 160; + start_spying(spyee, chan, &csth.spy); ast_activate_generator(chan, &spygen, &csth); - while(spy.status == CHANSPY_RUNNING && chan && !ast_check_hangup(chan) && spyee && !ast_check_hangup(spyee) && running == 1) { + while(csth.spy.status == CHANSPY_RUNNING && chan && !ast_check_hangup(chan) && spyee && !ast_check_hangup(spyee) && running == 1) { res = ast_waitfordigit(chan, 100); if (x == sizeof(inp)) { @@ -406,16 +445,16 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int } } ast_deactivate_generator(chan); - stop_spying(spyee, &spy); + stop_spying(spyee, &csth.spy); - if (option_verbose >= 2) + if (option_verbose >= 2) { ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name); - - ast_flush_spy_queue(&spy); + } + ast_flush_spy_queue(&csth.spy); } else { running = 0; } - ast_mutex_destroy(&spy.lock); + ast_mutex_destroy(&csth.spy.lock); return running; } @@ -423,23 +462,27 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int static int chanspy_exec(struct ast_channel *chan, void *data) { - int res=-1; struct localuser *u; struct ast_channel *peer=NULL, *prev=NULL; - char *ptr=NULL; - char name[AST_NAME_STRLEN], peer_name[AST_NAME_STRLEN]; - int count=0, waitms=100, num=0; - char *args; + char name[AST_NAME_STRLEN], + peer_name[AST_NAME_STRLEN], + *args, + *ptr = NULL, + *options = NULL, + *spec = NULL, + *argv[5], + *mygroup = NULL; + int res = -1, + volfactor = 0, + silent = 0, + argc = 0, + bronly = 0, + chosen = 0, + count=0, + waitms = 100, + num = 0; struct ast_flags flags; - char *options=NULL; - char *spec = NULL; - int volfactor=0; - int silent=0; - int argc = 0; - char *argv[5]; - char *mygroup = NULL; - int bronly = 0; - int chosen = 0; + if (!(args = ast_strdupa((char *)data))) { ast_log(LOG_ERROR, "Out of memory!\n"); @@ -450,6 +493,7 @@ static int chanspy_exec(struct ast_channel *chan, void *data) ast_log(LOG_ERROR, "Could Not Set Read Format.\n"); return -1; } + if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { ast_log(LOG_ERROR, "Could Not Set Write Format.\n"); return -1; -- cgit v1.2.3