aboutsummaryrefslogtreecommitdiffstats
path: root/apps/app_chanspy.c
diff options
context:
space:
mode:
authoranthm <anthm@f38db490-d61c-443f-a65b-d21fe96a405b>2005-03-31 18:00:35 +0000
committeranthm <anthm@f38db490-d61c-443f-a65b-d21fe96a405b>2005-03-31 18:00:35 +0000
commit20cd57249ce34509445ac99a97a8544ee0dedc76 (patch)
tree408a9461749ca4e8de78baeed0ac44d81debf066 /apps/app_chanspy.c
parentc3c585a0a2ad532a3d16d9b3d9d66615a03e565f (diff)
minor tweak and optimization for chanspy
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@5317 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps/app_chanspy.c')
-rwxr-xr-xapps/app_chanspy.c240
1 files 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;