2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Playback a file with audio detect
23 * \author Mark Spencer <markster@digium.com>
25 * \ingroup applications
30 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
32 #include "asterisk/lock.h"
33 #include "asterisk/file.h"
34 #include "asterisk/channel.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/module.h"
37 #include "asterisk/translate.h"
38 #include "asterisk/utils.h"
39 #include "asterisk/dsp.h"
40 #include "asterisk/app.h"
42 static char *app
= "BackgroundDetect";
44 static char *synopsis
= "Background a file with talk detect";
46 static char *descrip
=
47 " BackgroundDetect(filename[,sil[,min,[max]]]): Plays back a given\n"
48 "filename, waiting for interruption from a given digit (the digit must\n"
49 "start the beginning of a valid extension, or it will be ignored).\n"
50 "During the playback of the file, audio is monitored in the receive\n"
51 "direction, and if a period of non-silence which is greater than 'min' ms\n"
52 "yet less than 'max' ms is followed by silence for at least 'sil' ms then\n"
53 "the audio playback is aborted and processing jumps to the 'talk' extension\n"
54 "if available. If unspecified, sil, min, and max default to 1000, 100, and\n"
55 "infinity respectively.\n";
58 static int background_detect_exec(struct ast_channel
*chan
, void *data
)
64 struct timeval start
= { 0, 0};
70 struct ast_dsp
*dsp
= NULL
;
71 AST_DECLARE_APP_ARGS(args
,
72 AST_APP_ARG(filename
);
78 if (ast_strlen_zero(data
)) {
79 ast_log(LOG_WARNING
, "BackgroundDetect requires an argument (filename)\n");
83 tmp
= ast_strdupa(data
);
84 AST_STANDARD_APP_ARGS(args
, tmp
);
86 if (!ast_strlen_zero(args
.silence
) && (sscanf(args
.silence
, "%d", &x
) == 1) && (x
> 0))
88 if (!ast_strlen_zero(args
.min
) && (sscanf(args
.min
, "%d", &x
) == 1) && (x
> 0))
90 if (!ast_strlen_zero(args
.max
) && (sscanf(args
.max
, "%d", &x
) == 1) && (x
> 0))
93 ast_debug(1, "Preparing detect of '%s', sil=%d, min=%d, max=%d\n", args
.filename
, sil
, min
, max
);
95 if (chan
->_state
!= AST_STATE_UP
) {
96 if ((res
= ast_answer(chan
)))
100 origrformat
= chan
->readformat
;
101 if ((ast_set_read_format(chan
, AST_FORMAT_SLINEAR
))) {
102 ast_log(LOG_WARNING
, "Unable to set read format to linear!\n");
107 if (!(dsp
= ast_dsp_new())) {
108 ast_log(LOG_WARNING
, "Unable to allocate DSP!\n");
112 ast_stopstream(chan
);
113 if (ast_streamfile(chan
, tmp
, chan
->language
)) {
114 ast_log(LOG_WARNING
, "ast_streamfile failed on %s for %s\n", chan
->name
, (char *)data
);
118 while (chan
->stream
) {
119 res
= ast_sched_wait(chan
->sched
);
120 if ((res
< 0) && !chan
->timingfunc
) {
126 res
= ast_waitfor(chan
, res
);
128 ast_log(LOG_WARNING
, "Waitfor failed on %s\n", chan
->name
);
130 } else if (res
> 0) {
135 } else if (fr
->frametype
== AST_FRAME_DTMF
) {
139 if (ast_canmatch_extension(chan
, chan
->context
, t
, 1, chan
->cid
.cid_num
)) {
140 /* They entered a valid extension, or might be anyhow */
145 } else if ((fr
->frametype
== AST_FRAME_VOICE
) && (fr
->subclass
== AST_FORMAT_SLINEAR
)) {
148 res
= ast_dsp_silence(dsp
, fr
, &totalsilence
);
149 if (res
&& (totalsilence
> sil
)) {
150 /* We've been quiet a little while */
152 /* We had heard some talking */
153 ms
= ast_tvdiff_ms(ast_tvnow(), start
);
157 if ((ms
> min
) && ((max
< 0) || (ms
< max
))) {
159 ast_debug(1, "Found qualified token of %d ms\n", ms
);
161 /* Save detected talk time (in milliseconds) */
162 sprintf(ms_str
, "%d", ms
);
163 pbx_builtin_setvar_helper(chan
, "TALK_DETECTED", ms_str
);
165 ast_goto_if_exists(chan
, chan
->context
, "talk", 1);
170 ast_debug(1, "Found unqualified token of %d ms\n", ms
);
176 /* Heard some audio, mark the begining of the token */
178 ast_debug(1, "Start of voice token!\n");
185 ast_sched_runq(chan
->sched
);
187 ast_stopstream(chan
);
191 if (origrformat
&& ast_set_read_format(chan
, origrformat
)) {
192 ast_log(LOG_WARNING
, "Failed to restore read format for %s to %s\n",
193 chan
->name
, ast_getformatname(origrformat
));
201 static int unload_module(void)
203 return ast_unregister_application(app
);
206 static int load_module(void)
208 return ast_register_application(app
, background_detect_exec
, synopsis
, descrip
);
211 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Playback with Talk Detection");