2 * Asterisk -- A telephony toolkit for Linux.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
9 * - Waits for up to 'x' milliseconds of silence, 'y' times
10 * - WaitForSilence(500,2) will wait for 1/2 second of silence, twice
11 * - WaitForSilence(1000,1) will wait for 1 second of silence, once
13 * WaitForSilence Application by David C. Troy <dave@popvox.com>
14 * Version 1.00 2004-01-29
16 * This program is free software, distributed under the terms of
17 * the GNU General Public License
20 #include <asterisk/file.h>
21 #include <asterisk/logger.h>
22 #include <asterisk/channel.h>
23 #include <asterisk/pbx.h>
24 #include <asterisk/dsp.h>
25 #include <asterisk/module.h>
26 #include <asterisk/options.h>
32 static char *tdesc = "Wait For Silence";
33 static char *app = "WaitForSilence";
34 static char *synopsis = "Waits for a specified amount of silence";
35 static char *descrip =
36 " WaitForSilence(x[|y]) Wait for Silence: Waits for up to 'x' \n"
37 "milliseconds of silence, 'y' times or 1 if omitted\n"
39 " - WaitForSilence(500,2) will wait for 1/2 second of silence, twice\n"
40 " - WaitForSilence(1000) will wait for 1 second of silence, once\n";
46 static int do_waiting(struct ast_channel *chan, int maxsilence) {
52 static int silencethreshold = 64;
55 struct ast_dsp *sildet; /* silence detector dsp */
57 rfmt = chan->readformat; /* Set to linear mode */
58 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
60 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
64 sildet = ast_dsp_new(); /* Create the silence detector */
66 ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
69 ast_dsp_set_threshold(sildet, silencethreshold);
71 /* Await silence... */
74 res = ast_waitfor(chan, 2000);
76 ast_log(LOG_WARNING, "One waitfor failed, trying another\n");
77 /* Try one more time in case of masq */
78 res = ast_waitfor(chan, 2000);
80 ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
92 if (f->frametype == AST_FRAME_VOICE) {
94 ast_dsp_silence(sildet, f, &dspsilence);
96 totalsilence = dspsilence;
100 if (totalsilence >= maxsilence) {
101 if (option_verbose > 2)
102 ast_verbose(VERBOSE_PREFIX_3 "Exiting with %dms silence > %dms required\n", totalsilence, maxsilence);
103 /* Ended happily with silence */
111 if (rfmt && ast_set_read_format(chan, rfmt)) {
112 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
114 ast_dsp_free(sildet);
118 static int waitforsilence_exec(struct ast_channel *chan, void *data)
122 int maxsilence = 1000;
123 int iterations = 1, i;
125 res = ast_answer(chan); /* Answer the channel */
127 if (!data || ((sscanf(data, "%d|%d", &maxsilence, &iterations) != 2) &&
128 (sscanf(data, "%d", &maxsilence) != 1))) {
129 ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration\n");
132 if (option_verbose > 2)
133 ast_verbose(VERBOSE_PREFIX_3 "Waiting %d time(s) for %d ms silence\n", iterations, maxsilence);
136 for (i=0; (i<iterations) && (res == 1); i++) {
137 res = do_waiting(chan, maxsilence);
139 LOCAL_USER_REMOVE(u);
145 int unload_module(void)
147 STANDARD_HANGUP_LOCALUSERS;
148 return ast_unregister_application(app);
151 int load_module(void)
153 return ast_register_application(app, waitforsilence_exec, synopsis, descrip);
156 char *description(void)
164 STANDARD_USECOUNT(res);
170 return ASTERISK_GPL_KEY;