Merge "AST-2018-005: Fix tdata leaks when calling pjsip_endpt_send_response(2)"
[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 /*** MODULEINFO
42         <support_level>extended</support_level>
43  ***/
44
45 #include "asterisk.h"
46
47 #include "asterisk/app.h"
48 #include "asterisk/file.h"
49 #include "asterisk/channel.h"
50 #include "asterisk/pbx.h"
51 #include "asterisk/dsp.h"
52 #include "asterisk/module.h"
53 #include "asterisk/format_cache.h"
54
55 /*** DOCUMENTATION
56         <application name="WaitForSilence" language="en_US">
57                 <synopsis>
58                         Waits for a specified amount of silence.
59                 </synopsis>
60                 <syntax>
61                         <parameter name="silencerequired">
62                                 <para>If not specified, defaults to <literal>1000</literal> milliseconds.</para>
63                         </parameter>
64                         <parameter name="iterations">
65                                 <para>If not specified, defaults to <literal>1</literal>.</para>
66                         </parameter>
67                         <parameter name="timeout">
68                                 <para>Is specified only to avoid an infinite loop in cases where silence is never achieved.</para>
69                         </parameter>
70                 </syntax>
71                 <description>
72                         <para>Waits for up to <replaceable>silencerequired</replaceable> milliseconds of silence,
73                         <replaceable>iterations</replaceable> times. An optional <replaceable>timeout</replaceable>
74                         specified the number of seconds to return after, even if we do not receive the specified amount of silence.
75                         Use <replaceable>timeout</replaceable> with caution, as it may defeat the purpose of this application, which
76                         is to wait indefinitely until silence is detected on the line. This is particularly useful for reverse-911-type
77                         call broadcast applications where you need to wait for an answering machine to complete its spiel before
78                         playing a message.</para>
79                         <para>Typically you will want to include two or more calls to WaitForSilence when dealing with an answering
80                         machine; first waiting for the spiel to finish, then waiting for the beep, etc.</para>
81                         <para>Examples:</para>
82                         <para>WaitForSilence(500,2) will wait for 1/2 second of silence, twice</para>
83                         <para>WaitForSilence(1000) will wait for 1 second of silence, once</para>
84                         <para>WaitForSilence(300,3,10) will wait for 300ms silence, 3 times, and returns after 10 sec, even if silence
85                         is not detected</para>
86                         <para>Sets the channel variable <variable>WAITSTATUS</variable> to one of these values:</para>
87                         <variablelist>
88                                 <variable name="WAITSTATUS">
89                                         <value name="SILENCE">
90                                                 if exited with silence detected.
91                                         </value>
92                                         <value name="TIMEOUT">
93                                                 if exited without silence detected after timeout.
94                                         </value>
95                                 </variable>
96                         </variablelist>
97                 </description>
98                 <see-also>
99                         <ref type="application">WaitForNoise</ref>
100                 </see-also>
101         </application>
102         <application name="WaitForNoise" language="en_US">
103                 <synopsis>
104                         Waits for a specified amount of noise.
105                 </synopsis>
106                 <syntax>
107                         <parameter name="noiserequired">
108                                 <para>If not specified, defaults to <literal>1000</literal> milliseconds.</para>
109                         </parameter>
110                         <parameter name="iterations">
111                                 <para>If not specified, defaults to <literal>1</literal>.</para>
112                         </parameter>
113                         <parameter name="timeout">
114                                 <para>Is specified only to avoid an infinite loop in cases where silence is never achieved.</para>
115                         </parameter>
116                 </syntax>
117                 <description>
118                         <para>Waits for up to <replaceable>noiserequired</replaceable> milliseconds of noise,
119                         <replaceable>iterations</replaceable> times. An optional <replaceable>timeout</replaceable>
120                         specified the number of seconds to return after, even if we do not receive the specified amount of noise.
121                         Use <replaceable>timeout</replaceable> with caution, as it may defeat the purpose of this application, which
122                         is to wait indefinitely until noise is detected on the line.</para>
123                 </description>
124                 <see-also>
125                         <ref type="application">WaitForSilence</ref>
126                 </see-also>
127         </application>
128  ***/
129
130 static char *app_silence = "WaitForSilence";
131 static char *app_noise = "WaitForNoise";
132
133 struct wait_type {
134         const char *name;
135         const char *status;
136         int stop_on_frame_timeout;
137         int (*func)(struct ast_dsp *, struct ast_frame *, int *);
138 };
139
140 static const struct wait_type wait_for_silence = {
141         .name = "silence",
142         .status = "SILENCE",
143         .stop_on_frame_timeout = 1,
144         .func = ast_dsp_silence,
145 };
146
147 static const struct wait_type wait_for_noise = {
148         .name = "noise",
149         .status = "NOISE",
150         .stop_on_frame_timeout = 0,
151         .func = ast_dsp_noise,
152 };
153
154 static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int timeout, const struct wait_type *wait_for)
155 {
156         RAII_VAR(struct ast_format *, rfmt, NULL, ao2_cleanup);
157         int res;
158         struct ast_dsp *sildet;
159
160         rfmt = ao2_bump(ast_channel_readformat(chan));
161         if ((res = ast_set_read_format(chan, ast_format_slin)) < 0) {
162                 ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n");
163                 return -1;
164         }
165
166         /* Create the silence detector */
167         if (!(sildet = ast_dsp_new())) {
168                 ast_log(LOG_WARNING, "Unable to create silence detector\n");
169                 return -1;
170         }
171         ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
172
173         for (;;) {
174                 int dsptime = 0;
175
176                 res = ast_waitfor(chan, timereqd);
177
178                 /* Must have gotten a hangup; let's exit */
179                 if (res < 0) {
180                         pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
181                         break;
182                 }
183
184                 /* We waited and got no frame; sounds like digital silence or a muted digital channel */
185                 if (res == 0) {
186                         if (wait_for->stop_on_frame_timeout) {
187                                 dsptime = timereqd;
188                         }
189                 } else {
190                         /* Looks like we did get a frame, so let's check it out */
191                         struct ast_frame *f = ast_read(chan);
192                         if (!f) {
193                                 pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
194                                 break;
195                         }
196                         if (f->frametype == AST_FRAME_VOICE) {
197                                 wait_for->func(sildet, f, &dsptime);
198                         }
199                         ast_frfree(f);
200                 }
201
202                 ast_debug(1, "Got %dms of %s < %dms required\n", dsptime, wait_for->name, timereqd);
203
204                 if (dsptime >= timereqd) {
205                         ast_verb(3, "Exiting with %dms of %s >= %dms required\n", dsptime, wait_for->name, timereqd);
206                         pbx_builtin_setvar_helper(chan, "WAITSTATUS", wait_for->status);
207                         ast_debug(1, "WAITSTATUS was set to %s\n", wait_for->status);
208                         res = 1;
209                         break;
210                 }
211
212                 if (timeout && difftime(time(NULL), waitstart) >= timeout) {
213                         pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
214                         ast_debug(1, "WAITSTATUS was set to TIMEOUT\n");
215                         res = 0;
216                         break;
217                 }
218         }
219
220         if (rfmt && ast_set_read_format(chan, rfmt)) {
221                 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_format_get_name(rfmt), ast_channel_name(chan));
222         }
223
224         ast_dsp_free(sildet);
225         return res;
226 }
227
228 static int waitfor_exec(struct ast_channel *chan, const char *data, const struct wait_type *wait_for)
229 {
230         int res = 1;
231         int timereqd = 1000;
232         int timeout = 0;
233         int iterations = 1, i;
234         time_t waitstart;
235         char *parse;
236         struct ast_silence_generator *silgen = NULL;
237
238         AST_DECLARE_APP_ARGS(args,
239                 AST_APP_ARG(timereqd);
240                 AST_APP_ARG(iterations);
241                 AST_APP_ARG(timeout);
242         );
243
244         parse = ast_strdupa(data);
245         AST_STANDARD_APP_ARGS(args, parse);
246
247         if (!ast_strlen_zero(args.timereqd)) {
248                 if (sscanf(args.timereqd, "%30d", &timereqd) != 1 || timereqd < 0) {
249                         ast_log(LOG_ERROR, "Argument '%srequired' must be an integer greater than or equal to zero.\n",
250                                         wait_for->name);
251                         return -1;
252                 }
253         }
254
255         if (!ast_strlen_zero(args.iterations)) {
256                 if (sscanf(args.iterations, "%30d", &iterations) != 1 || iterations < 1) {
257                         ast_log(LOG_ERROR, "Argument 'iterations' must be an integer greater than 0.\n");
258                         return -1;
259                 }
260         }
261
262         if (!ast_strlen_zero(args.timeout)) {
263                 if (sscanf(args.timeout, "%30d", &timeout) != 1 || timeout < 0) {
264                         ast_log(LOG_ERROR, "Argument 'timeout' must be an integer greater than or equal to zero.\n");
265                         return -1;
266                 }
267         }
268
269         if (ast_channel_state(chan) != AST_STATE_UP) {
270                 ast_answer(chan); /* Answer the channel */
271         }
272
273         ast_verb(3, "Waiting %d time(s) for %dms of %s with %ds timeout\n",
274                          iterations, timereqd, wait_for->name, timeout);
275
276         if (ast_opt_transmit_silence) {
277                 silgen = ast_channel_start_silence_generator(chan);
278         }
279
280         time(&waitstart);
281         for (i = 0; i < iterations && res == 1; i++) {
282                 res = do_waiting(chan, timereqd, waitstart, timeout, wait_for);
283         }
284
285         if (silgen) {
286                 ast_channel_stop_silence_generator(chan, silgen);
287         }
288
289         return res > 0 ? 0 : res;
290 }
291
292 static int waitforsilence_exec(struct ast_channel *chan, const char *data)
293 {
294         return waitfor_exec(chan, data, &wait_for_silence);
295 }
296
297 static int waitfornoise_exec(struct ast_channel *chan, const char *data)
298 {
299         return waitfor_exec(chan, data, &wait_for_noise);
300 }
301
302 static int unload_module(void)
303 {
304         int res;
305         res = ast_unregister_application(app_silence);
306         res |= ast_unregister_application(app_noise);
307
308         return res;
309 }
310
311 static int load_module(void)
312 {
313         int res;
314
315         res = ast_register_application_xml(app_silence, waitforsilence_exec);
316         res |= ast_register_application_xml(app_noise, waitfornoise_exec);
317         return res;
318 }
319
320 AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Wait For Silence/Noise");