Wed Jan 8 2020 09:49:55

Asterisk developer's documentation


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"

Go to the source code of this file.

Functions

static void __reg_module (void)
 
static void __unreg_module (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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
 
static char * app = "BackgroundDetect"
 
static 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

static void __reg_module ( void  )
static

Definition at line 256 of file app_talkdetect.c.

static void __unreg_module ( void  )
static

Definition at line 256 of file app_talkdetect.c.

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

Definition at line 80 of file app_talkdetect.c.

References ast_channel::_state, args, ast_answer(), AST_APP_ARG, ast_canmatch_extension(), ast_debug, AST_DECLARE_APP_ARGS, ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, ast_getformatname(), 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_channel::caller, ast_frame_subclass::codec, ast_channel::context, ast_frame::frametype, ast_party_caller::id, ast_frame_subclass::integer, ast_channel::language, LOG_WARNING, ast_channel::name, ast_party_id::number, pbx_builtin_setvar_helper(), ast_channel::readformat, S_COR, ast_channel::sched, ast_party_number::str, ast_channel::stream, ast_frame::subclass, ast_channel::timingfunc, ast_dsp::totalsilence, and ast_party_number::valid.

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  int origrformat = 0;
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 (chan->_state != AST_STATE_UP) {
128  if ((res = ast_answer(chan))) {
129  break;
130  }
131  }
132 
133  origrformat = chan->readformat;
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, chan->language)) {
147  ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
148  break;
149  }
150  detection_start = ast_tvnow();
151  while (chan->stream) {
152  res = ast_sched_wait(chan->sched);
153  if ((res < 0) && !chan->timingfunc) {
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", chan->name);
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", chan->name);
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, chan->context, t, 1,
183  S_COR(chan->caller.id.number.valid, chan->caller.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) && (fr->subclass.codec == AST_FORMAT_SLINEAR) && continue_analysis) {
190  int totalsilence;
191  int ms;
192  res = ast_dsp_silence(dsp, fr, &totalsilence);
193  if (res && (totalsilence > sil)) {
194  /* We've been quiet a little while */
195  if (notsilent) {
196  /* We had heard some talking */
197  ms = ast_tvdiff_ms(ast_tvnow(), start);
198  ms -= sil;
199  if (ms < 0)
200  ms = 0;
201  if ((ms > min) && ((max < 0) || (ms < max))) {
202  char ms_str[12];
203  ast_debug(1, "Found qualified token of %d ms\n", ms);
204 
205  /* Save detected talk time (in milliseconds) */
206  snprintf(ms_str, sizeof(ms_str), "%d", ms);
207  pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);
208 
209  ast_goto_if_exists(chan, chan->context, "talk", 1);
210  res = 0;
211  ast_frfree(fr);
212  break;
213  } else {
214  ast_debug(1, "Found unqualified token of %d ms\n", ms);
215  }
216  notsilent = 0;
217  }
218  } else {
219  if (!notsilent) {
220  /* Heard some audio, mark the begining of the token */
221  start = ast_tvnow();
222  ast_debug(1, "Start of voice token!\n");
223  notsilent = 1;
224  }
225  }
226  }
227  ast_frfree(fr);
228  }
229  ast_sched_runq(chan->sched);
230  }
231  ast_stopstream(chan);
232  } while (0);
233 
234  if (res > -1) {
235  if (origrformat && ast_set_read_format(chan, origrformat)) {
236  ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n",
237  chan->name, ast_getformatname(origrformat));
238  }
239  }
240  if (dsp) {
241  ast_dsp_free(dsp);
242  }
243  return res;
244 }
union ast_frame_subclass subclass
Definition: frame.h:146
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1650
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define LOG_WARNING
Definition: logger.h:144
struct ast_dsp * ast_dsp_new(void)
Definition: dsp.c:1607
#define AST_FRAME_DTMF
Definition: frame.h:128
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
format_t codec
Definition: frame.h:137
#define ast_verb(level,...)
Definition: logger.h:243
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:5415
int totalsilence
Definition: dsp.c:393
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
Definition: dsp.c:390
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#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:83
struct sched_context * sched
Definition: channel.h:756
int(* timingfunc)(const void *data)
Definition: channel.h:759
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
static struct @350 args
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:11261
int ast_sched_runq(struct sched_context *con)
Runs the queue.
Definition: sched.c:600
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...
Definition: pbx.c:10546
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Return non-zero if this is silence. Updates &quot;totalsilence&quot; with the total number of seconds of silenc...
Definition: dsp.c:1355
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
format_t readformat
Definition: channel.h:853
int ast_sched_wait(struct sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place Determine the number of s...
Definition: sched.c:334
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
Data structure associated with a single frame of data.
Definition: frame.h:142
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
struct ast_filestream * stream
Definition: channel.h:757
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
const ast_string_field language
Definition: channel.h:787
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int load_module ( void  )
static

Definition at line 251 of file app_talkdetect.c.

References ast_register_application_xml, and background_detect_exec().

252 {
254 }
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:437
static int unload_module ( void  )
static

Definition at line 246 of file app_talkdetect.c.

References ast_unregister_application().

247 {
249 }
static char * app
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705

Variable Documentation

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 256 of file app_talkdetect.c.

char* app = "BackgroundDetect"
static

Definition at line 78 of file app_talkdetect.c.

Definition at line 256 of file app_talkdetect.c.