Wed Jan 8 2020 09:49:42

Asterisk developer's documentation


app_waitforsilence.c
Go to the documentation of this file.
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 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
48 
49 #include "asterisk/file.h"
50 #include "asterisk/channel.h"
51 #include "asterisk/pbx.h"
52 #include "asterisk/dsp.h"
53 #include "asterisk/module.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" required="true" />
62  <parameter name="iterations">
63  <para>If not specified, defaults to <literal>1</literal>.</para>
64  </parameter>
65  <parameter name="timeout">
66  <para>Is specified only to avoid an infinite loop in cases where silence is never achieved.</para>
67  </parameter>
68  </syntax>
69  <description>
70  <para>Waits for up to <replaceable>silencerequired</replaceable> milliseconds of silence,
71  <replaceable>iterations</replaceable> times. An optional <replaceable>timeout</replaceable>
72  specified the number of seconds to return after, even if we do not receive the specified amount of silence.
73  Use <replaceable>timeout</replaceable> with caution, as it may defeat the purpose of this application, which
74  is to wait indefinitely until silence is detected on the line. This is particularly useful for reverse-911-type
75  call broadcast applications where you need to wait for an answering machine to complete its spiel before
76  playing a message.</para>
77  <para>Typically you will want to include two or more calls to WaitForSilence when dealing with an answering
78  machine; first waiting for the spiel to finish, then waiting for the beep, etc.</para>
79  <para>Examples:</para>
80  <para>WaitForSilence(500,2) will wait for 1/2 second of silence, twice</para>
81  <para>WaitForSilence(1000) will wait for 1 second of silence, once</para>
82  <para>WaitForSilence(300,3,10) will wait for 300ms silence, 3 times, and returns after 10 sec, even if silence
83  is not detected</para>
84  <para>Sets the channel variable <variable>WAITSTATUS</variable> to one of these values:</para>
85  <variablelist>
86  <variable name="WAITSTATUS">
87  <value name="SILENCE">
88  if exited with silence detected.
89  </value>
90  <value name="TIMEOUT">
91  if exited without silence detected after timeout.
92  </value>
93  </variable>
94  </variablelist>
95  </description>
96  <see-also>
97  <ref type="application">WaitForNoise</ref>
98  </see-also>
99  </application>
100  <application name="WaitForNoise" language="en_US">
101  <synopsis>
102  Waits for a specified amount of noise.
103  </synopsis>
104  <syntax>
105  <parameter name="noiserequired" required="true" />
106  <parameter name="iterations">
107  <para>If not specified, defaults to <literal>1</literal>.</para>
108  </parameter>
109  <parameter name="timeout">
110  <para>Is specified only to avoid an infinite loop in cases where silence is never achieved.</para>
111  </parameter>
112  </syntax>
113  <description>
114  <para>Waits for up to <replaceable>noiserequired</replaceable> milliseconds of noise,
115  <replaceable>iterations</replaceable> times. An optional <replaceable>timeout</replaceable>
116  specified the number of seconds to return after, even if we do not receive the specified amount of noise.
117  Use <replaceable>timeout</replaceable> with caution, as it may defeat the purpose of this application, which
118  is to wait indefinitely until noise is detected on the line.</para>
119  </description>
120  <see-also>
121  <ref type="application">WaitForSilence</ref>
122  </see-also>
123  </application>
124  ***/
125 
126 static char *app_silence = "WaitForSilence";
127 static char *app_noise = "WaitForNoise";
128 
129 static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int timeout, int wait_for_silence) {
130  struct ast_frame *f = NULL;
131  int dsptime = 0;
132  int rfmt = 0;
133  int res = 0;
134  struct ast_dsp *sildet; /* silence detector dsp */
135  time_t now;
136 
137  /*Either silence or noise calc depending on wait_for_silence flag*/
138  int (*ast_dsp_func)(struct ast_dsp*, struct ast_frame*, int*) =
139  wait_for_silence ? ast_dsp_silence : ast_dsp_noise;
140 
141  rfmt = chan->readformat; /* Set to linear mode */
142  if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
143  ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n");
144  return -1;
145  }
146 
147  /* Create the silence detector */
148  if (!(sildet = ast_dsp_new())) {
149  ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
150  return -1;
151  }
153 
154  /* Await silence... */
155  for (;;) {
156  /* Start with no silence received */
157  dsptime = 0;
158 
159  res = ast_waitfor(chan, timereqd);
160 
161  /* Must have gotten a hangup; let's exit */
162  if (res < 0) {
163  pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
164  break;
165  }
166 
167  /* We waited and got no frame; sounds like digital silence or a muted digital channel */
168  if (res == 0) {
169  dsptime = timereqd;
170  } else {
171  /* Looks like we did get a frame, so let's check it out */
172  if (!(f = ast_read(chan))) {
173  pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
174  break;
175  }
176  if (f->frametype == AST_FRAME_VOICE) {
177  ast_dsp_func(sildet, f, &dsptime);
178  }
179  ast_frfree(f);
180  }
181 
182  ast_verb(6, "Got %dms %s < %dms required\n", dsptime, wait_for_silence ? "silence" : "noise", timereqd);
183 
184  if (dsptime >= timereqd) {
185  ast_verb(3, "Exiting with %dms %s >= %dms required\n", dsptime, wait_for_silence ? "silence" : "noise", timereqd);
186  /* Ended happily with silence */
187  res = 1;
188  pbx_builtin_setvar_helper(chan, "WAITSTATUS", wait_for_silence ? "SILENCE" : "NOISE");
189  ast_debug(1, "WAITSTATUS was set to %s\n", wait_for_silence ? "SILENCE" : "NOISE");
190  break;
191  }
192 
193  if (timeout && (difftime(time(&now), waitstart) >= timeout)) {
194  pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
195  ast_debug(1, "WAITSTATUS was set to TIMEOUT\n");
196  res = 0;
197  break;
198  }
199  }
200 
201 
202  if (rfmt && ast_set_read_format(chan, rfmt)) {
203  ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
204  }
205  ast_dsp_free(sildet);
206  return res;
207 }
208 
209 static int waitfor_exec(struct ast_channel *chan, const char *data, int wait_for_silence)
210 {
211  int res = 1;
212  int timereqd = 1000;
213  int timeout = 0;
214  int iterations = 1, i;
215  time_t waitstart;
216  struct ast_silence_generator *silgen = NULL;
217 
218  if (chan->_state != AST_STATE_UP) {
219  res = ast_answer(chan); /* Answer the channel */
220  }
221 
222  if (!data || ( (sscanf(data, "%30d,%30d,%30d", &timereqd, &iterations, &timeout) != 3) &&
223  (sscanf(data, "%30d,%30d", &timereqd, &iterations) != 2) &&
224  (sscanf(data, "%30d", &timereqd) != 1) ) ) {
225  ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration, no timeout\n");
226  }
227 
228  ast_verb(3, "Waiting %d time(s) for %d ms silence with %d timeout\n", iterations, timereqd, timeout);
229 
232  }
233  time(&waitstart);
234  res = 1;
235  for (i=0; (i<iterations) && (res == 1); i++) {
236  res = do_waiting(chan, timereqd, waitstart, timeout, wait_for_silence);
237  }
238  if (silgen) {
240  }
241 
242 
243  if (res > 0)
244  res = 0;
245  return res;
246 }
247 
248 static int waitforsilence_exec(struct ast_channel *chan, const char *data)
249 {
250  return waitfor_exec(chan, data, 1);
251 }
252 
253 static int waitfornoise_exec(struct ast_channel *chan, const char *data)
254 {
255  return waitfor_exec(chan, data, 0);
256 }
257 
258 static int unload_module(void)
259 {
260  int res;
261  res = ast_unregister_application(app_silence);
262  res |= ast_unregister_application(app_noise);
263 
264  return res;
265 }
266 
267 static int load_module(void)
268 {
269  int res;
270 
273  return res;
274 }
275 
277 
static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int timeout, int wait_for_silence)
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
Asterisk main include file. File version handling, generic pbx functions.
static int waitforsilence_exec(struct ast_channel *chan, const char *data)
static int unload_module(void)
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1650
Convenient Signal Processing routines.
#define LOG_WARNING
Definition: logger.h:144
struct ast_dsp * ast_dsp_new(void)
Definition: dsp.c:1607
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
#define ast_opt_transmit_silence
Definition: options.h:120
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
#define ast_verb(level,...)
Definition: logger.h:243
static char * app_silence
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
General Asterisk PBX channel definitions.
Definition: dsp.c:390
static char * app_noise
static int waitfor_exec(struct ast_channel *chan, const char *data, int wait_for_silence)
Core PBX routines and definitions.
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set threshold value for silence.
Definition: dsp.c:1655
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
Definition: channel.c:8309
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
Stops a previously-started silence generator on the given channel.
Definition: channel.c:8355
static struct ast_format f[]
Definition: format_g726.c:181
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Return non-zero if this is silence. Updates &quot;totalsilence&quot; with the total number of seconds of silenc...
Definition: dsp.c:1355
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
format_t readformat
Definition: channel.h:853
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
static int load_module(void)
#define ast_frfree(fr)
Definition: frame.h:583
static int waitfornoise_exec(struct ast_channel *chan, const char *data)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:1880
Asterisk module definitions.
union ast_frame::@172 data
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
int ast_dsp_noise(struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
Return non-zero if this is noise. Updates &quot;totalnoise&quot; with the total number of seconds of noise...
Definition: dsp.c:1373