Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 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:3190
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:4274
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5779
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:2834
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:1301
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:8796
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:4205
#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:157
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, 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 = "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 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.