Merged revisions 149061 via svnmerge from
[asterisk/asterisk.git] / apps / app_waitforsilence.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * WaitForSilence Application by David C. Troy <dave@popvox.com>
7  * Version 1.11 2006-06-29
8  *
9  * Mark Spencer <markster@digium.com>
10  *
11  * See http://www.asterisk.org for more information about
12  * the Asterisk project. Please do not directly contact
13  * any of the maintainers of this project for assistance;
14  * the project provides a web site, mailing lists and IRC
15  * channels for your use.
16  *
17  * This program is free software, distributed under the terms of
18  * the GNU General Public License Version 2. See the LICENSE file
19  * at the top of the source tree.
20  */
21
22 /*! \file
23  *
24  * \brief Wait for Silence
25  *   - Waits for up to 'x' milliseconds of silence, 'y' times \n
26  *   - WaitForSilence(500,2) will wait for 1/2 second of silence, twice \n
27  *   - WaitForSilence(1000,1) will wait for 1 second of silence, once \n
28  *   - WaitForSilence(300,3,10) will wait for 300ms of silence, 3 times, and return after 10sec \n
29  *
30  * \author David C. Troy <dave@popvox.com>
31  *
32  * \brief Wait For Noise
33  * The same as Wait For Silence but listenes noise on the chennel that is above \n
34  * the pre-configured silence threshold from dsp.conf
35  *
36  * \author Philipp Skadorov <skadorov@yahoo.com>
37  *
38  * \ingroup applications
39  */
40
41 #include "asterisk.h"
42
43 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
44
45 #include "asterisk/file.h"
46 #include "asterisk/channel.h"
47 #include "asterisk/pbx.h"
48 #include "asterisk/dsp.h"
49 #include "asterisk/module.h"
50
51 static char *app_silence = "WaitForSilence";
52 static char *synopsis_silence = "Waits for a specified amount of silence";
53 static char *descrip_silence =
54 "  WaitForSilence(silencerequired[,iterations][,timeout]):\n"
55 "Wait for Silence: Waits for up to 'silencerequired' \n"
56 "milliseconds of silence, 'iterations' times or once if omitted.\n"
57 "An optional timeout specified the number of seconds to return\n"
58 "after, even if we do not receive the specified amount of silence.\n"
59 "Use 'timeout' with caution, as it may defeat the purpose of this\n"
60 "application, which is to wait indefinitely until silence is detected\n"
61 "on the line.  This is particularly useful for reverse-911-type\n"
62 "call broadcast applications where you need to wait for an answering\n"
63 "machine to complete its spiel before playing a message.\n"
64 "The timeout parameter is specified only to avoid an infinite loop in\n"
65 "cases where silence is never achieved.  Typically you will want to\n"
66 "include two or more calls to WaitForSilence when dealing with an answering\n"
67 "machine; first waiting for the spiel to finish, then waiting for the beep, etc.\n\n"
68   "Examples:\n"
69 "  - WaitForSilence(500,2) will wait for 1/2 second of silence, twice\n"
70 "  - WaitForSilence(1000) will wait for 1 second of silence, once\n"
71 "  - WaitForSilence(300,3,10) will wait for 300ms silence, 3 times,\n"
72 "     and returns after 10 sec, even if silence is not detected\n\n"
73 "Sets the channel variable WAITSTATUS with to one of these values:\n"
74 "SILENCE - if exited with silence detected\n"
75 "TIMEOUT - if exited without silence detected after timeout\n";
76
77 static char *app_noise = "WaitForNoise";
78 static char *synopsis_noise = "Waits for a specified amount of noise";
79 static char *descrip_noise =
80 "WaitForNoise(noiserequired[,iterations][,timeout]) \n"
81 "Wait for Noise: The same as Wait for Silance but waits for noise that is above the threshold specified\n";
82
83 static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int timeout, int wait_for_silence) {
84         struct ast_frame *f = NULL;
85         int dsptime = 0;
86         int rfmt = 0;
87         int res = 0;
88         struct ast_dsp *sildet;  /* silence detector dsp */
89         time_t now;
90
91         /*Either silence or noise calc depending on wait_for_silence flag*/
92         int (*ast_dsp_func)(struct ast_dsp*, struct ast_frame*, int*) =
93                                 wait_for_silence ? ast_dsp_silence : ast_dsp_noise;
94
95         rfmt = chan->readformat; /* Set to linear mode */
96         if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
97                 ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n");
98                 return -1;
99         }
100
101         /* Create the silence detector */
102         if (!(sildet = ast_dsp_new())) {
103                 ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
104                 return -1;
105         }
106         ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
107
108         /* Await silence... */
109         for (;;) {
110                 /* Start with no silence received */
111                 dsptime = 0;
112
113                 res = ast_waitfor(chan, timereqd);
114
115                 /* Must have gotten a hangup; let's exit */
116                 if (res < 0) {
117                         pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
118                         break;
119                 }
120                 
121                 /* We waited and got no frame; sounds like digital silence or a muted digital channel */
122                 if (res == 0) {
123                         dsptime = timereqd;
124                 } else {
125                         /* Looks like we did get a frame, so let's check it out */
126                         if (!(f = ast_read(chan))) {
127                                 pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
128                                 break;
129                         }
130                         if (f->frametype == AST_FRAME_VOICE) {
131                                 ast_dsp_func(sildet, f, &dsptime);
132                         }
133                         ast_frfree(f);
134                 }
135
136                 ast_verb(6, "Got %dms %s < %dms required\n", dsptime, wait_for_silence ? "silence" : "noise", timereqd);
137
138                 if (dsptime >= timereqd) {
139                         ast_verb(3, "Exiting with %dms %s >= %dms required\n", dsptime, wait_for_silence ? "silence" : "noise", timereqd);
140                         /* Ended happily with silence */
141                         res = 1;
142                         pbx_builtin_setvar_helper(chan, "WAITSTATUS", wait_for_silence ? "SILENCE" : "NOISE");
143                         ast_debug(1, "WAITSTATUS was set to %s\n", wait_for_silence ? "SILENCE" : "NOISE");
144                         break;
145                 }
146
147                 if (timeout && (difftime(time(&now), waitstart) >= timeout)) {
148                         pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
149                         ast_debug(1, "WAITSTATUS was set to TIMEOUT\n");
150                         res = 0;
151                         break;
152                 }
153         }
154
155
156         if (rfmt && ast_set_read_format(chan, rfmt)) {
157                 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
158         }
159         ast_dsp_free(sildet);
160         return res;
161 }
162
163 static int waitfor_exec(struct ast_channel *chan, void *data, int wait_for_silence)
164 {
165         int res = 1;
166         int timereqd = 1000;
167         int timeout = 0;
168         int iterations = 1, i;
169         time_t waitstart;
170
171         res = ast_answer(chan); /* Answer the channel */
172
173         if (!data || ( (sscanf(data, "%d,%d,%d", &timereqd, &iterations, &timeout) != 3) &&
174                 (sscanf(data, "%d,%d", &timereqd, &iterations) != 2) &&
175                 (sscanf(data, "%d", &timereqd) != 1) ) ) {
176                 ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration, no timeout\n");
177         }
178
179         ast_verb(3, "Waiting %d time(s) for %d ms silence with %d timeout\n", iterations, timereqd, timeout);
180
181         time(&waitstart);
182         res = 1;
183         for (i=0; (i<iterations) && (res == 1); i++) {
184                 res = do_waiting(chan, timereqd, waitstart, timeout, wait_for_silence);
185         }
186         if (res > 0)
187                 res = 0;
188         return res;
189 }
190
191 static int waitforsilence_exec(struct ast_channel *chan, void *data)
192 {
193         return waitfor_exec(chan, data, 1);
194 }
195
196 static int waitfornoise_exec(struct ast_channel *chan, void *data)
197 {
198         return waitfor_exec(chan, data, 0);
199 }
200
201 static int unload_module(void)
202 {
203         int res;
204         res = ast_unregister_application(app_silence);
205         res |= ast_unregister_application(app_noise);
206
207         return res;
208 }
209
210 static int load_module(void)
211 {
212         int res;
213
214         res = ast_register_application(app_silence, waitforsilence_exec, synopsis_silence, descrip_silence);
215         res |= ast_register_application(app_noise, waitfornoise_exec, synopsis_noise, descrip_noise);
216         return res;
217 }
218
219 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Wait For Silence");
220