Wed Jan 8 2020 09:49:52

Asterisk developer's documentation


app_amd.c File Reference

Answering machine detection. More...

#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/app.h"

Go to the source code of this file.

Macros

#define STATE_IN_SILENCE   2
 
#define STATE_IN_WORD   1
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int amd_exec (struct ast_channel *chan, const char *data)
 
static void isAnsweringMachine (struct ast_channel *chan, const char *data)
 
static int load_config (int reload)
 
static int load_module (void)
 
static int reload (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Answering Machine Detection Application" , .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, .reload = reload, }
 
static const char app [] = "AMD"
 
static struct ast_module_infoast_module_info = &__mod_info
 
static int dfltAfterGreetingSilence = 800
 
static int dfltBetweenWordsSilence = 50
 
static int dfltGreeting = 1500
 
static int dfltInitialSilence = 2500
 
static int dfltMaximumNumberOfWords = 3
 
static int dfltMaximumWordLength = 5000
 
static int dfltMaxWaitTimeForFrame = 50
 
static int dfltMinimumWordLength = 100
 
static int dfltSilenceThreshold = 256
 
static int dfltTotalAnalysisTime = 5000
 

Detailed Description

Answering machine detection.

Author
Claude Klimos (claud.nosp@m.e.kl.nosp@m.imos@.nosp@m.ahee.nosp@m.va.co.nosp@m.m)

Definition in file app_amd.c.

Macro Definition Documentation

#define STATE_IN_SILENCE   2

Definition at line 133 of file app_amd.c.

Referenced by isAnsweringMachine().

#define STATE_IN_WORD   1

Definition at line 132 of file app_amd.c.

Referenced by isAnsweringMachine().

Function Documentation

static void __reg_module ( void  )
static

Definition at line 508 of file app_amd.c.

static void __unreg_module ( void  )
static

Definition at line 508 of file app_amd.c.

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

Definition at line 412 of file app_amd.c.

References isAnsweringMachine().

Referenced by load_module().

413 {
414  isAnsweringMachine(chan, data);
415 
416  return 0;
417 }
static void isAnsweringMachine(struct ast_channel *chan, const char *data)
Definition: app_amd.c:149
static void isAnsweringMachine ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 149 of file app_amd.c.

References ast_party_caller::ani, args, AST_APP_ARG, ast_codec_get_samples(), ast_debug, AST_DECLARE_APP_ARGS, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_CNG, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree, ast_getformatname(), ast_log(), ast_read(), ast_set_read_format(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_verb, ast_waitfor(), ast_channel::caller, DEFAULT_SAMPLES_PER_MS, dfltAfterGreetingSilence, dfltBetweenWordsSilence, dfltGreeting, dfltInitialSilence, dfltMaximumNumberOfWords, dfltMaximumWordLength, dfltMaxWaitTimeForFrame, dfltMinimumWordLength, dfltSilenceThreshold, dfltTotalAnalysisTime, f, ast_frame::frametype, ast_party_redirecting::from, LOG_WARNING, ast_channel::name, ast_party_id::number, parse(), pbx_builtin_setvar_helper(), ast_channel::readformat, ast_channel::redirecting, S_COR, STATE_IN_SILENCE, STATE_IN_WORD, ast_party_number::str, and ast_party_number::valid.

Referenced by amd_exec().

150 {
151  int res = 0;
152  struct ast_frame *f = NULL;
153  struct ast_dsp *silenceDetector = NULL;
154  int dspsilence = 0, readFormat, framelength = 0;
155  int inInitialSilence = 1;
156  int inGreeting = 0;
157  int voiceDuration = 0;
158  int silenceDuration = 0;
159  int iTotalTime = 0;
160  int iWordsCount = 0;
161  int currentState = STATE_IN_WORD;
162  int consecutiveVoiceDuration = 0;
163  char amdCause[256] = "", amdStatus[256] = "";
164  char *parse = ast_strdupa(data);
165 
166  /* Lets set the initial values of the variables that will control the algorithm.
167  The initial values are the default ones. If they are passed as arguments
168  when invoking the application, then the default values will be overwritten
169  by the ones passed as parameters. */
170  int initialSilence = dfltInitialSilence;
171  int greeting = dfltGreeting;
172  int afterGreetingSilence = dfltAfterGreetingSilence;
173  int totalAnalysisTime = dfltTotalAnalysisTime;
174  int minimumWordLength = dfltMinimumWordLength;
175  int betweenWordsSilence = dfltBetweenWordsSilence;
176  int maximumNumberOfWords = dfltMaximumNumberOfWords;
177  int silenceThreshold = dfltSilenceThreshold;
178  int maximumWordLength = dfltMaximumWordLength;
179  int maxWaitTimeForFrame = dfltMaxWaitTimeForFrame;
180 
182  AST_APP_ARG(argInitialSilence);
183  AST_APP_ARG(argGreeting);
184  AST_APP_ARG(argAfterGreetingSilence);
185  AST_APP_ARG(argTotalAnalysisTime);
186  AST_APP_ARG(argMinimumWordLength);
187  AST_APP_ARG(argBetweenWordsSilence);
188  AST_APP_ARG(argMaximumNumberOfWords);
189  AST_APP_ARG(argSilenceThreshold);
190  AST_APP_ARG(argMaximumWordLength);
191  );
192 
193  ast_verb(3, "AMD: %s %s %s (Fmt: %s)\n", chan->name,
194  S_COR(chan->caller.ani.number.valid, chan->caller.ani.number.str, "(N/A)"),
195  S_COR(chan->redirecting.from.number.valid, chan->redirecting.from.number.str, "(N/A)"),
197 
198  /* Lets parse the arguments. */
199  if (!ast_strlen_zero(parse)) {
200  /* Some arguments have been passed. Lets parse them and overwrite the defaults. */
201  AST_STANDARD_APP_ARGS(args, parse);
202  if (!ast_strlen_zero(args.argInitialSilence))
203  initialSilence = atoi(args.argInitialSilence);
204  if (!ast_strlen_zero(args.argGreeting))
205  greeting = atoi(args.argGreeting);
206  if (!ast_strlen_zero(args.argAfterGreetingSilence))
207  afterGreetingSilence = atoi(args.argAfterGreetingSilence);
208  if (!ast_strlen_zero(args.argTotalAnalysisTime))
209  totalAnalysisTime = atoi(args.argTotalAnalysisTime);
210  if (!ast_strlen_zero(args.argMinimumWordLength))
211  minimumWordLength = atoi(args.argMinimumWordLength);
212  if (!ast_strlen_zero(args.argBetweenWordsSilence))
213  betweenWordsSilence = atoi(args.argBetweenWordsSilence);
214  if (!ast_strlen_zero(args.argMaximumNumberOfWords))
215  maximumNumberOfWords = atoi(args.argMaximumNumberOfWords);
216  if (!ast_strlen_zero(args.argSilenceThreshold))
217  silenceThreshold = atoi(args.argSilenceThreshold);
218  if (!ast_strlen_zero(args.argMaximumWordLength))
219  maximumWordLength = atoi(args.argMaximumWordLength);
220  } else {
221  ast_debug(1, "AMD using the default parameters.\n");
222  }
223 
224  /* Find lowest ms value, that will be max wait time for a frame */
225  if (maxWaitTimeForFrame > initialSilence)
226  maxWaitTimeForFrame = initialSilence;
227  if (maxWaitTimeForFrame > greeting)
228  maxWaitTimeForFrame = greeting;
229  if (maxWaitTimeForFrame > afterGreetingSilence)
230  maxWaitTimeForFrame = afterGreetingSilence;
231  if (maxWaitTimeForFrame > totalAnalysisTime)
232  maxWaitTimeForFrame = totalAnalysisTime;
233  if (maxWaitTimeForFrame > minimumWordLength)
234  maxWaitTimeForFrame = minimumWordLength;
235  if (maxWaitTimeForFrame > betweenWordsSilence)
236  maxWaitTimeForFrame = betweenWordsSilence;
237 
238  /* Now we're ready to roll! */
239  ast_verb(3, "AMD: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
240  "totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] maximumWordLength [%d] \n",
241  initialSilence, greeting, afterGreetingSilence, totalAnalysisTime,
242  minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold, maximumWordLength);
243 
244  /* Set read format to signed linear so we get signed linear frames in */
245  readFormat = chan->readformat;
246  if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0 ) {
247  ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to set to linear mode, giving up\n", chan->name );
248  pbx_builtin_setvar_helper(chan , "AMDSTATUS", "");
249  pbx_builtin_setvar_helper(chan , "AMDCAUSE", "");
250  return;
251  }
252 
253  /* Create a new DSP that will detect the silence */
254  if (!(silenceDetector = ast_dsp_new())) {
255  ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to create silence detector :(\n", chan->name );
256  pbx_builtin_setvar_helper(chan , "AMDSTATUS", "");
257  pbx_builtin_setvar_helper(chan , "AMDCAUSE", "");
258  return;
259  }
260 
261  /* Set silence threshold to specified value */
262  ast_dsp_set_threshold(silenceDetector, silenceThreshold);
263 
264  /* Now we go into a loop waiting for frames from the channel */
265  while ((res = ast_waitfor(chan, 2 * maxWaitTimeForFrame)) > -1) {
266 
267  /* If we fail to read in a frame, that means they hung up */
268  if (!(f = ast_read(chan))) {
269  ast_verb(3, "AMD: Channel [%s]. HANGUP\n", chan->name);
270  ast_debug(1, "Got hangup\n");
271  strcpy(amdStatus, "HANGUP");
272  res = 1;
273  break;
274  }
275 
277  /* If the total time exceeds the analysis time then give up as we are not too sure */
278  if (f->frametype == AST_FRAME_VOICE) {
279  framelength = (ast_codec_get_samples(f) / DEFAULT_SAMPLES_PER_MS);
280  } else {
281  framelength = 2 * maxWaitTimeForFrame;
282  }
283 
284  iTotalTime += framelength;
285  if (iTotalTime >= totalAnalysisTime) {
286  ast_verb(3, "AMD: Channel [%s]. Too long...\n", chan->name );
287  ast_frfree(f);
288  strcpy(amdStatus , "NOTSURE");
289  sprintf(amdCause , "TOOLONG-%d", iTotalTime);
290  break;
291  }
292 
293  /* Feed the frame of audio into the silence detector and see if we get a result */
294  if (f->frametype != AST_FRAME_VOICE)
295  dspsilence += 2 * maxWaitTimeForFrame;
296  else {
297  dspsilence = 0;
298  ast_dsp_silence(silenceDetector, f, &dspsilence);
299  }
300 
301  if (dspsilence > 0) {
302  silenceDuration = dspsilence;
303 
304  if (silenceDuration >= betweenWordsSilence) {
305  if (currentState != STATE_IN_SILENCE ) {
306  ast_verb(3, "AMD: Channel [%s]. Changed state to STATE_IN_SILENCE\n", chan->name);
307  }
308  /* Find words less than word duration */
309  if (consecutiveVoiceDuration < minimumWordLength && consecutiveVoiceDuration > 0){
310  ast_verb(3, "AMD: Channel [%s]. Short Word Duration: %d\n", chan->name, consecutiveVoiceDuration);
311  }
312  currentState = STATE_IN_SILENCE;
313  consecutiveVoiceDuration = 0;
314  }
315 
316  if (inInitialSilence == 1 && silenceDuration >= initialSilence) {
317  ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: silenceDuration:%d initialSilence:%d\n",
318  chan->name, silenceDuration, initialSilence);
319  ast_frfree(f);
320  strcpy(amdStatus , "MACHINE");
321  sprintf(amdCause , "INITIALSILENCE-%d-%d", silenceDuration, initialSilence);
322  res = 1;
323  break;
324  }
325 
326  if (silenceDuration >= afterGreetingSilence && inGreeting == 1) {
327  ast_verb(3, "AMD: Channel [%s]. HUMAN: silenceDuration:%d afterGreetingSilence:%d\n",
328  chan->name, silenceDuration, afterGreetingSilence);
329  ast_frfree(f);
330  strcpy(amdStatus , "HUMAN");
331  sprintf(amdCause , "HUMAN-%d-%d", silenceDuration, afterGreetingSilence);
332  res = 1;
333  break;
334  }
335 
336  } else {
337  consecutiveVoiceDuration += framelength;
338  voiceDuration += framelength;
339 
340  /* If I have enough consecutive voice to say that I am in a Word, I can only increment the
341  number of words if my previous state was Silence, which means that I moved into a word. */
342  if (consecutiveVoiceDuration >= minimumWordLength && currentState == STATE_IN_SILENCE) {
343  iWordsCount++;
344  ast_verb(3, "AMD: Channel [%s]. Word detected. iWordsCount:%d\n", chan->name, iWordsCount);
345  currentState = STATE_IN_WORD;
346  }
347  if (consecutiveVoiceDuration >= maximumWordLength){
348  ast_verb(3, "AMD: Channel [%s]. Maximum Word Length detected. [%d]\n", chan->name, consecutiveVoiceDuration);
349  ast_frfree(f);
350  strcpy(amdStatus , "MACHINE");
351  sprintf(amdCause , "MAXWORDLENGTH-%d", consecutiveVoiceDuration);
352  break;
353  }
354  if (iWordsCount >= maximumNumberOfWords) {
355  ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: iWordsCount:%d\n", chan->name, iWordsCount);
356  ast_frfree(f);
357  strcpy(amdStatus , "MACHINE");
358  sprintf(amdCause , "MAXWORDS-%d-%d", iWordsCount, maximumNumberOfWords);
359  res = 1;
360  break;
361  }
362 
363  if (inGreeting == 1 && voiceDuration >= greeting) {
364  ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: voiceDuration:%d greeting:%d\n", chan->name, voiceDuration, greeting);
365  ast_frfree(f);
366  strcpy(amdStatus , "MACHINE");
367  sprintf(amdCause , "LONGGREETING-%d-%d", voiceDuration, greeting);
368  res = 1;
369  break;
370  }
371 
372  if (voiceDuration >= minimumWordLength ) {
373  if (silenceDuration > 0)
374  ast_verb(3, "AMD: Channel [%s]. Detected Talk, previous silence duration: %d\n", chan->name, silenceDuration);
375  silenceDuration = 0;
376  }
377  if (consecutiveVoiceDuration >= minimumWordLength && inGreeting == 0) {
378  /* Only go in here once to change the greeting flag when we detect the 1st word */
379  if (silenceDuration > 0)
380  ast_verb(3, "AMD: Channel [%s]. Before Greeting Time: silenceDuration: %d voiceDuration: %d\n", chan->name, silenceDuration, voiceDuration);
381  inInitialSilence = 0;
382  inGreeting = 1;
383  }
384 
385  }
386  }
387  ast_frfree(f);
388  }
389 
390  if (!res) {
391  /* It took too long to get a frame back. Giving up. */
392  ast_verb(3, "AMD: Channel [%s]. Too long...\n", chan->name);
393  strcpy(amdStatus , "NOTSURE");
394  sprintf(amdCause , "TOOLONG-%d", iTotalTime);
395  }
396 
397  /* Set the status and cause on the channel */
398  pbx_builtin_setvar_helper(chan , "AMDSTATUS" , amdStatus);
399  pbx_builtin_setvar_helper(chan , "AMDCAUSE" , amdCause);
400 
401  /* Restore channel read format */
402  if (readFormat && ast_set_read_format(chan, readFormat))
403  ast_log(LOG_WARNING, "AMD: Unable to restore read format on '%s'\n", chan->name);
404 
405  /* Free the DSP used to detect silence */
406  ast_dsp_free(silenceDetector);
407 
408  return;
409 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
static int dfltTotalAnalysisTime
Definition: app_amd.c:139
static int dfltSilenceThreshold
Definition: app_amd.c:143
static int dfltMinimumWordLength
Definition: app_amd.c:140
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:449
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1650
#define LOG_WARNING
Definition: logger.h:144
struct ast_dsp * ast_dsp_new(void)
Definition: dsp.c:1607
static int dfltMaximumWordLength
Definition: app_amd.c:144
#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 ast_party_redirecting redirecting
Redirecting/Diversion information.
Definition: channel.h:814
static int dfltInitialSilence
Definition: app_amd.c:136
#define ast_verb(level,...)
Definition: logger.h:243
static int dfltBetweenWordsSilence
Definition: app_amd.c:141
static int dfltMaximumNumberOfWords
Definition: app_amd.c:142
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 STATE_IN_WORD
Definition: app_amd.c:132
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:377
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
static int dfltAfterGreetingSilence
Definition: app_amd.c:138
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set threshold value for silence.
Definition: dsp.c:1655
#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
static int dfltMaxWaitTimeForFrame
Definition: app_amd.c:147
#define STATE_IN_SILENCE
Definition: app_amd.c:133
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
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static struct ast_format f[]
Definition: format_g726.c:181
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_codec_get_samples(struct ast_frame *f)
Returns the number of samples contained in the frame.
Definition: frame.c:1470
#define DEFAULT_SAMPLES_PER_MS
Definition: asterisk.h:42
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
static int dfltGreeting
Definition: app_amd.c:137
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int load_config ( int  reload)
static

Definition at line 419 of file app_amd.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load, ast_dsp_get_threshold_from_settings(), ast_log(), ast_variable_browse(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, THRESHOLD_SILENCE, ast_variable::value, and var.

Referenced by load_module(), and reload().

420 {
421  struct ast_config *cfg = NULL;
422  char *cat = NULL;
423  struct ast_variable *var = NULL;
424  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
425 
427 
428  if (!(cfg = ast_config_load("amd.conf", config_flags))) {
429  ast_log(LOG_ERROR, "Configuration file amd.conf missing.\n");
430  return -1;
431  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
432  return 0;
433  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
434  ast_log(LOG_ERROR, "Config file amd.conf is in an invalid format. Aborting.\n");
435  return -1;
436  }
437 
438  cat = ast_category_browse(cfg, NULL);
439 
440  while (cat) {
441  if (!strcasecmp(cat, "general") ) {
442  var = ast_variable_browse(cfg, cat);
443  while (var) {
444  if (!strcasecmp(var->name, "initial_silence")) {
445  dfltInitialSilence = atoi(var->value);
446  } else if (!strcasecmp(var->name, "greeting")) {
447  dfltGreeting = atoi(var->value);
448  } else if (!strcasecmp(var->name, "after_greeting_silence")) {
449  dfltAfterGreetingSilence = atoi(var->value);
450  } else if (!strcasecmp(var->name, "silence_threshold")) {
451  dfltSilenceThreshold = atoi(var->value);
452  } else if (!strcasecmp(var->name, "total_analysis_time")) {
453  dfltTotalAnalysisTime = atoi(var->value);
454  } else if (!strcasecmp(var->name, "min_word_length")) {
455  dfltMinimumWordLength = atoi(var->value);
456  } else if (!strcasecmp(var->name, "between_words_silence")) {
457  dfltBetweenWordsSilence = atoi(var->value);
458  } else if (!strcasecmp(var->name, "maximum_number_of_words")) {
459  dfltMaximumNumberOfWords = atoi(var->value);
460  } else if (!strcasecmp(var->name, "maximum_word_length")) {
461  dfltMaximumWordLength = atoi(var->value);
462 
463  } else {
464  ast_log(LOG_WARNING, "%s: Cat:%s. Unknown keyword %s at line %d of amd.conf\n",
465  app, cat, var->name, var->lineno);
466  }
467  var = var->next;
468  }
469  }
470  cat = ast_category_browse(cfg, cat);
471  }
472 
473  ast_config_destroy(cfg);
474 
475  ast_verb(3, "AMD defaults: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
476  "totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] maximumWordLength [%d]\n",
479 
480  return 0;
481 }
static int dfltTotalAnalysisTime
Definition: app_amd.c:139
static int dfltSilenceThreshold
Definition: app_amd.c:143
static int dfltMinimumWordLength
Definition: app_amd.c:140
#define LOG_WARNING
Definition: logger.h:144
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
int lineno
Definition: config.h:87
static int dfltMaximumWordLength
Definition: app_amd.c:144
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
static int dfltInitialSilence
Definition: app_amd.c:136
#define ast_verb(level,...)
Definition: logger.h:243
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static int dfltBetweenWordsSilence
Definition: app_amd.c:141
static int dfltMaximumNumberOfWords
Definition: app_amd.c:142
const char * value
Definition: config.h:79
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
static int dfltAfterGreetingSilence
Definition: app_amd.c:138
const char * name
Definition: config.h:77
static const char app[]
Definition: app_amd.c:130
static int reload(void)
Definition: app_amd.c:497
#define LOG_ERROR
Definition: logger.h:155
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
Structure used to handle boolean flags.
Definition: utils.h:200
struct ast_variable * next
Definition: config.h:82
static int dfltGreeting
Definition: app_amd.c:137
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:1880
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
static int load_module ( void  )
static

Definition at line 488 of file app_amd.c.

References amd_exec(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, and load_config().

489 {
490  if (load_config(0))
495 }
static const char app[]
Definition: app_amd.c:130
static int amd_exec(struct ast_channel *chan, const char *data)
Definition: app_amd.c:412
static int load_config(int reload)
Definition: app_amd.c:419
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static int reload ( void  )
static

Definition at line 497 of file app_amd.c.

References AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, and load_config().

498 {
499  if (load_config(1))
502 }
static int load_config(int reload)
Definition: app_amd.c:419
static int unload_module ( void  )
static

Definition at line 483 of file app_amd.c.

References ast_unregister_application().

484 {
486 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static const char app[]
Definition: app_amd.c:130

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Answering Machine Detection Application" , .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, .reload = reload, }
static

Definition at line 508 of file app_amd.c.

const char app[] = "AMD"
static

Definition at line 130 of file app_amd.c.

Definition at line 508 of file app_amd.c.

int dfltAfterGreetingSilence = 800
static

Definition at line 138 of file app_amd.c.

Referenced by isAnsweringMachine().

int dfltBetweenWordsSilence = 50
static

Definition at line 141 of file app_amd.c.

Referenced by isAnsweringMachine().

int dfltGreeting = 1500
static

Definition at line 137 of file app_amd.c.

Referenced by isAnsweringMachine().

int dfltInitialSilence = 2500
static

Definition at line 136 of file app_amd.c.

Referenced by isAnsweringMachine().

int dfltMaximumNumberOfWords = 3
static

Definition at line 142 of file app_amd.c.

Referenced by isAnsweringMachine().

int dfltMaximumWordLength = 5000
static

Definition at line 144 of file app_amd.c.

Referenced by isAnsweringMachine().

int dfltMaxWaitTimeForFrame = 50
static

Definition at line 147 of file app_amd.c.

Referenced by isAnsweringMachine().

int dfltMinimumWordLength = 100
static

Definition at line 140 of file app_amd.c.

Referenced by isAnsweringMachine().

int dfltSilenceThreshold = 256
static

Definition at line 143 of file app_amd.c.

Referenced by isAnsweringMachine().

int dfltTotalAnalysisTime = 5000
static

Definition at line 139 of file app_amd.c.

Referenced by isAnsweringMachine().