Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
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 = ASTERISK_GPL_KEY , .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 260 of file app_talkdetect.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 260 of file app_talkdetect.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 260 of file app_talkdetect.c.

◆ background_detect_exec()

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

Definition at line 83 of file app_talkdetect.c.

84{
85 int res = 0;
86 char *tmp;
87 struct ast_frame *fr;
88 int notsilent = 0;
89 struct timeval start = { 0, 0 };
90 struct timeval detection_start = { 0, 0 };
91 int sil = 1000;
92 int min = 100;
93 int max = -1;
94 int analysistime = -1;
95 int continue_analysis = 1;
96 int x;
97 RAII_VAR(struct ast_format *, origrformat, NULL, ao2_cleanup);
98 struct ast_dsp *dsp = NULL;
100 AST_APP_ARG(filename);
101 AST_APP_ARG(silence);
104 AST_APP_ARG(analysistime);
105 );
106
107 if (ast_strlen_zero(data)) {
108 ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n");
109 return -1;
110 }
111
112 tmp = ast_strdupa(data);
114
115 if (!ast_strlen_zero(args.silence) && (sscanf(args.silence, "%30d", &x) == 1) && (x > 0)) {
116 sil = x;
117 }
118 if (!ast_strlen_zero(args.min) && (sscanf(args.min, "%30d", &x) == 1) && (x > 0)) {
119 min = x;
120 }
121 if (!ast_strlen_zero(args.max) && (sscanf(args.max, "%30d", &x) == 1) && (x > 0)) {
122 max = x;
123 }
124 if (!ast_strlen_zero(args.analysistime) && (sscanf(args.analysistime, "%30d", &x) == 1) && (x > 0)) {
125 analysistime = x;
126 }
127
128 ast_debug(1, "Preparing detect of '%s', sil=%d, min=%d, max=%d, analysistime=%d\n", args.filename, sil, min, max, analysistime);
129 do {
130 if (ast_channel_state(chan) != AST_STATE_UP) {
131 if ((res = ast_answer(chan))) {
132 break;
133 }
134 }
135
136 origrformat = ao2_bump(ast_channel_readformat(chan));
138 ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
139 res = -1;
140 break;
141 }
142
143 if (!(dsp = ast_dsp_new())) {
144 ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
145 res = -1;
146 break;
147 }
148 ast_stopstream(chan);
149 if (ast_streamfile(chan, tmp, ast_channel_language(chan))) {
150 ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", ast_channel_name(chan), (char *)data);
151 break;
152 }
153 detection_start = ast_tvnow();
154 while (ast_channel_stream(chan)) {
156 if ((res < 0) && !ast_channel_timingfunc(chan)) {
157 res = 0;
158 break;
159 }
160 if (res < 0) {
161 res = 1000;
162 }
163 res = ast_waitfor(chan, res);
164 if (res < 0) {
165 ast_log(LOG_WARNING, "Waitfor failed on %s\n", ast_channel_name(chan));
166 break;
167 } else if (res > 0) {
168 fr = ast_read(chan);
169 if (continue_analysis && analysistime >= 0) {
170 /* If we have a limit for the time to analyze voice
171 * frames and the time has not expired */
172 if (ast_tvdiff_ms(ast_tvnow(), detection_start) >= analysistime) {
173 continue_analysis = 0;
174 ast_verb(3, "BackgroundDetect: Talk analysis time complete on %s.\n", ast_channel_name(chan));
175 }
176 }
177
178 if (!fr) {
179 res = -1;
180 break;
181 } else if (fr->frametype == AST_FRAME_DTMF) {
182 char t[2];
183 t[0] = fr->subclass.integer;
184 t[1] = '\0';
185 if (ast_canmatch_extension(chan, ast_channel_context(chan), t, 1,
186 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
187 /* They entered a valid extension, or might be anyhow */
188 res = fr->subclass.integer;
189 ast_frfree(fr);
190 break;
191 }
192 } else if ((fr->frametype == AST_FRAME_VOICE) &&
193 (ast_format_cmp(fr->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) && continue_analysis) {
194 int totalsilence;
195 int ms;
196 res = ast_dsp_silence(dsp, fr, &totalsilence);
197 if (res && (totalsilence > sil)) {
198 /* We've been quiet a little while */
199 if (notsilent) {
200 /* We had heard some talking */
201 ms = ast_tvdiff_ms(ast_tvnow(), start);
202 ms -= sil;
203 if (ms < 0)
204 ms = 0;
205 if ((ms > min) && ((max < 0) || (ms < max))) {
206 char ms_str[12];
207 ast_debug(1, "Found qualified token of %d ms\n", ms);
208
209 /* Save detected talk time (in milliseconds) */
210 snprintf(ms_str, sizeof(ms_str), "%d", ms);
211 pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);
212
213 ast_goto_if_exists(chan, ast_channel_context(chan), "talk", 1);
214 res = 0;
215 ast_frfree(fr);
216 break;
217 } else {
218 ast_debug(1, "Found unqualified token of %d ms\n", ms);
219 }
220 notsilent = 0;
221 }
222 } else {
223 if (!notsilent) {
224 /* Heard some audio, mark the begining of the token */
225 start = ast_tvnow();
226 ast_debug(1, "Start of voice token!\n");
227 notsilent = 1;
228 }
229 }
230 }
231 ast_frfree(fr);
232 }
234 }
235 ast_stopstream(chan);
236 } while (0);
237
238 if (res > -1) {
239 if (origrformat && ast_set_read_format(chan, origrformat)) {
240 ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n",
241 ast_channel_name(chan), ast_format_get_name(origrformat));
242 }
243 }
244 if (dsp) {
245 ast_dsp_free(dsp);
246 }
247 return res;
248}
#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
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:3159
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:4250
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition channel.c:5757
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:2803
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
ast_channel_state
ast_channel states
@ AST_STATE_UP
void ast_dsp_free(struct ast_dsp *dsp)
Definition dsp.c:1787
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition dsp.c:1492
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition dsp.c:1762
#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:223
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition file.c:1312
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.
#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)
#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:8806
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:4211
static struct @519 args
#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.
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:981

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, and ast_dsp::totalsilence.

Referenced by load_module().

◆ load_module()

static int load_module ( void  )
static

Definition at line 255 of file app_talkdetect.c.

256{
258}
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 250 of file app_talkdetect.c.

251{
253}
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 = ASTERISK_GPL_KEY , .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 260 of file app_talkdetect.c.

◆ app

char* app = "BackgroundDetect"
static

Definition at line 81 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 260 of file app_talkdetect.c.