Asterisk - The Open Source Telephony Project GIT-master-f36a736
Functions | Variables
app_talkdetect.c File Reference

Playback a file with audio detect. More...

#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/utils.h"
#include "asterisk/dsp.h"
#include "asterisk/app.h"
#include "asterisk/format.h"
#include "asterisk/format_cache.h"
Include dependency graph for app_talkdetect.c:

Go to the source code of this file.

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int background_detect_exec (struct ast_channel *chan, const char *data)
 
static int load_module (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Playback with Talk Detection" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static char * app = "BackgroundDetect"
 
static const struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

Playback a file with audio detect.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file app_talkdetect.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 257 of file app_talkdetect.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 257 of file app_talkdetect.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 257 of file app_talkdetect.c.

◆ background_detect_exec()

static int background_detect_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 80 of file app_talkdetect.c.

81{
82 int res = 0;
83 char *tmp;
84 struct ast_frame *fr;
85 int notsilent = 0;
86 struct timeval start = { 0, 0 };
87 struct timeval detection_start = { 0, 0 };
88 int sil = 1000;
89 int min = 100;
90 int max = -1;
91 int analysistime = -1;
92 int continue_analysis = 1;
93 int x;
94 RAII_VAR(struct ast_format *, origrformat, NULL, ao2_cleanup);
95 struct ast_dsp *dsp = NULL;
97 AST_APP_ARG(filename);
98 AST_APP_ARG(silence);
101 AST_APP_ARG(analysistime);
102 );
103
104 if (ast_strlen_zero(data)) {
105 ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n");
106 return -1;
107 }
108
109 tmp = ast_strdupa(data);
111
112 if (!ast_strlen_zero(args.silence) && (sscanf(args.silence, "%30d", &x) == 1) && (x > 0)) {
113 sil = x;
114 }
115 if (!ast_strlen_zero(args.min) && (sscanf(args.min, "%30d", &x) == 1) && (x > 0)) {
116 min = x;
117 }
118 if (!ast_strlen_zero(args.max) && (sscanf(args.max, "%30d", &x) == 1) && (x > 0)) {
119 max = x;
120 }
121 if (!ast_strlen_zero(args.analysistime) && (sscanf(args.analysistime, "%30d", &x) == 1) && (x > 0)) {
122 analysistime = x;
123 }
124
125 ast_debug(1, "Preparing detect of '%s', sil=%d, min=%d, max=%d, analysistime=%d\n", args.filename, sil, min, max, analysistime);
126 do {
127 if (ast_channel_state(chan) != AST_STATE_UP) {
128 if ((res = ast_answer(chan))) {
129 break;
130 }
131 }
132
133 origrformat = ao2_bump(ast_channel_readformat(chan));
135 ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
136 res = -1;
137 break;
138 }
139
140 if (!(dsp = ast_dsp_new())) {
141 ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
142 res = -1;
143 break;
144 }
145 ast_stopstream(chan);
146 if (ast_streamfile(chan, tmp, ast_channel_language(chan))) {
147 ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", ast_channel_name(chan), (char *)data);
148 break;
149 }
150 detection_start = ast_tvnow();
151 while (ast_channel_stream(chan)) {
153 if ((res < 0) && !ast_channel_timingfunc(chan)) {
154 res = 0;
155 break;
156 }
157 if (res < 0) {
158 res = 1000;
159 }
160 res = ast_waitfor(chan, res);
161 if (res < 0) {
162 ast_log(LOG_WARNING, "Waitfor failed on %s\n", ast_channel_name(chan));
163 break;
164 } else if (res > 0) {
165 fr = ast_read(chan);
166 if (continue_analysis && analysistime >= 0) {
167 /* If we have a limit for the time to analyze voice
168 * frames and the time has not expired */
169 if (ast_tvdiff_ms(ast_tvnow(), detection_start) >= analysistime) {
170 continue_analysis = 0;
171 ast_verb(3, "BackgroundDetect: Talk analysis time complete on %s.\n", ast_channel_name(chan));
172 }
173 }
174
175 if (!fr) {
176 res = -1;
177 break;
178 } else if (fr->frametype == AST_FRAME_DTMF) {
179 char t[2];
180 t[0] = fr->subclass.integer;
181 t[1] = '\0';
182 if (ast_canmatch_extension(chan, ast_channel_context(chan), t, 1,
183 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
184 /* They entered a valid extension, or might be anyhow */
185 res = fr->subclass.integer;
186 ast_frfree(fr);
187 break;
188 }
189 } else if ((fr->frametype == AST_FRAME_VOICE) &&
190 (ast_format_cmp(fr->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) && continue_analysis) {
191 int totalsilence;
192 int ms;
193 res = ast_dsp_silence(dsp, fr, &totalsilence);
194 if (res && (totalsilence > sil)) {
195 /* We've been quiet a little while */
196 if (notsilent) {
197 /* We had heard some talking */
198 ms = ast_tvdiff_ms(ast_tvnow(), start);
199 ms -= sil;
200 if (ms < 0)
201 ms = 0;
202 if ((ms > min) && ((max < 0) || (ms < max))) {
203 char ms_str[12];
204 ast_debug(1, "Found qualified token of %d ms\n", ms);
205
206 /* Save detected talk time (in milliseconds) */
207 snprintf(ms_str, sizeof(ms_str), "%d", ms);
208 pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);
209
210 ast_goto_if_exists(chan, ast_channel_context(chan), "talk", 1);
211 res = 0;
212 ast_frfree(fr);
213 break;
214 } else {
215 ast_debug(1, "Found unqualified token of %d ms\n", ms);
216 }
217 notsilent = 0;
218 }
219 } else {
220 if (!notsilent) {
221 /* Heard some audio, mark the begining of the token */
222 start = ast_tvnow();
223 ast_debug(1, "Start of voice token!\n");
224 notsilent = 1;
225 }
226 }
227 }
228 ast_frfree(fr);
229 }
231 }
232 ast_stopstream(chan);
233 } while (0);
234
235 if (res > -1) {
236 if (origrformat && ast_set_read_format(chan, origrformat)) {
237 ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n",
238 ast_channel_name(chan), ast_format_get_name(origrformat));
239 }
240 }
241 if (dsp) {
242 ast_dsp_free(dsp);
243 }
244 return res;
245}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static int tmp()
Definition: bt_open.c:389
const char * ast_channel_name(const struct ast_channel *chan)
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3181
const char * ast_channel_context(const struct ast_channel *chan)
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4276
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5781
ast_timing_func_t ast_channel_timingfunc(const struct ast_channel *chan)
const char * ast_channel_language(const struct ast_channel *chan)
struct ast_sched_context * ast_channel_sched(const struct ast_channel *chan)
struct ast_filestream * ast_channel_stream(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2824
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1783
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition: dsp.c:1488
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
#define min(a, b)
Definition: f2c.h:197
#define max(a, b)
Definition: f2c.h:198
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:222
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1293
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
@ AST_FORMAT_CMP_EQUAL
Definition: format.h:36
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_FRAME_DTMF
#define ast_frfree(fr)
@ AST_FRAME_VOICE
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define LOG_WARNING
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.
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8781
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:4190
#define NULL
Definition: resample.c:96
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:786
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:433
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Definition: dsp.c:407
int totalsilence
Definition: dsp.c:411
Definition of a media format.
Definition: format.c:43
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
Number structure.
Definition: app_followme.c:154
const char * args
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ao2_bump, ao2_cleanup, args, ast_answer(), AST_APP_ARG, ast_canmatch_extension(), ast_channel_caller(), ast_channel_context(), ast_channel_language(), ast_channel_name(), ast_channel_readformat(), ast_channel_sched(), ast_channel_stream(), ast_channel_timingfunc(), ast_debug, AST_DECLARE_APP_ARGS, ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_get_name(), ast_format_slin, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, ast_goto_if_exists(), ast_log, ast_read(), ast_sched_runq(), ast_sched_wait(), ast_set_read_format(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, ast_waitfor(), ast_frame_subclass::format, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, max, min, NULL, pbx_builtin_setvar_helper(), RAII_VAR, S_COR, ast_frame::subclass, tmp(), and ast_dsp::totalsilence.

Referenced by load_module().

◆ load_module()

static int load_module ( void  )
static

Definition at line 252 of file app_talkdetect.c.

253{
255}
static int background_detect_exec(struct ast_channel *chan, const char *data)
static char * app
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640

References app, ast_register_application_xml, and background_detect_exec().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 247 of file app_talkdetect.c.

248{
250}
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392

References app, and ast_unregister_application().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Playback with Talk Detection" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 257 of file app_talkdetect.c.

◆ app

char* app = "BackgroundDetect"
static

Definition at line 78 of file app_talkdetect.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 257 of file app_talkdetect.c.