Asterisk - The Open Source Telephony Project  18.5.0
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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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.

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().

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);
99  AST_APP_ARG(min);
100  AST_APP_ARG(max);
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));
134  if ((ast_set_read_format(chan, ast_format_slin))) {
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)) {
152  res = ast_sched_wait(ast_channel_sched(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 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1250
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:755
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1745
static int tmp()
Definition: bt_open.c:389
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
ast_channel_state
ast_channel states
Definition: channelstate.h:35
Definition of a media format.
Definition: format.c:43
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
const char * args
#define NULL
Definition: resample.c:96
#define AST_FRAME_DTMF
#define ast_verb(level,...)
Definition: logger.h:463
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:4194
struct ast_frame_subclass subclass
int totalsilence
Definition: dsp.c:409
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
Number structure.
Definition: app_followme.c:154
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
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
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5849
#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:911
Definition: dsp.c:405
#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:85
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct ast_sched_context * ast_channel_sched(const struct ast_channel *chan)
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8793
struct ast_filestream * ast_channel_stream(const struct ast_channel *chan)
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_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition: dsp.c:1483
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_frfree(fr)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
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:431
Data structure associated with a single frame of data.
const char * ast_channel_language(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
enum ast_frame_type frametype
struct ast_format * format
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
ast_timing_func_t ast_channel_timingfunc(const struct ast_channel *chan)
#define min(a, b)
Definition: f2c.h:197
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187
#define AST_APP_ARG(name)
Define an application argument.
#define max(a, b)
Definition: f2c.h:198

◆ load_module()

static int load_module ( void  )
static

Definition at line 252 of file app_talkdetect.c.

References app, ast_register_application_xml, and background_detect_exec().

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

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 247 of file app_talkdetect.c.

References app, and ast_unregister_application().

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

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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.