Asterisk - The Open Source Telephony Project  18.5.0
Macros | Enumerations | Functions | Variables
app_mf.c File Reference

MF sender and receiver applications. More...

#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/conversions.h"
Include dependency graph for app_mf.c:

Go to the source code of this file.

Macros

#define MF_BETWEEN_MS   50
 
#define MF_DURATION   55
 
#define MF_KP_DURATION   120
 
#define MF_ST_DURATION   65
 

Enumerations

enum  read_option_flags {
  OPT_DELAY = (1 << 0), OPT_MUTE = (1 << 1), OPT_QUELCH = (1 << 2), OPT_RELAXED = (1 << 3),
  OPT_LAX_KP = (1 << 4), OPT_PROCESS = (1 << 5), OPT_NO_KP = (1 << 6), OPT_NO_ST = (1 << 7),
  OPT_KP_OVERRIDE = (1 << 8), OPT_EXTRAPULSES = (1 << 9), OPT_SKIP = (1 << 0), OPT_INDICATION = (1 << 1),
  OPT_NOANSWER = (1 << 2)
}
 

Functions

 AST_MODULE_INFO_STANDARD_EXTENDED (ASTERISK_GPL_KEY, "MF Sender and Receiver Applications")
 
static int load_module (void)
 
static int manager_play_mf (struct mansession *s, const struct message *m)
 
static int read_mf_digits (struct ast_channel *chan, char *buf, int timeout, int features, int laxkp, int override, int no_kp, int no_st)
 Detects MF digits on channel using DSP, terminated by ST, STP, ST2P, or ST3P. More...
 
static int read_mf_exec (struct ast_channel *chan, const char *data)
 
static int read_sf_digits (struct ast_channel *chan, char *buf, int timeout, int maxdigits, int freq, int features, int extrapulses)
 
static int read_sf_exec (struct ast_channel *chan, const char *data)
 
static int sendmf_exec (struct ast_channel *chan, const char *vdata)
 
static int unload_module (void)
 

Variables

static const struct ast_app_option read_app_options [128] = { [ 'd' ] = { .flag = OPT_DELAY }, [ 'e' ] = { .flag = OPT_EXTRAPULSES }, [ 'l' ] = { .flag = OPT_LAX_KP }, [ 'k' ] = { .flag = OPT_NO_KP }, [ 'm' ] = { .flag = OPT_MUTE }, [ 'o' ] = { .flag = OPT_KP_OVERRIDE }, [ 'p' ] = { .flag = OPT_PROCESS }, [ 'q' ] = { .flag = OPT_QUELCH }, [ 'r' ] = { .flag = OPT_RELAXED }, [ 's' ] = { .flag = OPT_NO_ST }, }
 
static char * readmf_name = "ReceiveMF"
 
static char * readsf_name = "ReceiveSF"
 
static const char sendmf_name [] = "SendMF"
 

Detailed Description

MF sender and receiver applications.

Author
Naveen Albert aster.nosp@m.isk@.nosp@m.phrea.nosp@m.knet.nosp@m..org

Definition in file app_mf.c.

Macro Definition Documentation

◆ MF_BETWEEN_MS

#define MF_BETWEEN_MS   50

Definition at line 262 of file app_mf.c.

Referenced by sendmf_exec().

◆ MF_DURATION

#define MF_DURATION   55

Definition at line 263 of file app_mf.c.

Referenced by manager_play_mf(), and sendmf_exec().

◆ MF_KP_DURATION

#define MF_KP_DURATION   120

Definition at line 264 of file app_mf.c.

Referenced by manager_play_mf(), and sendmf_exec().

◆ MF_ST_DURATION

#define MF_ST_DURATION   65

Definition at line 265 of file app_mf.c.

Referenced by manager_play_mf(), and sendmf_exec().

Enumeration Type Documentation

◆ read_option_flags

Enumerator
OPT_DELAY 
OPT_MUTE 
OPT_QUELCH 
OPT_RELAXED 
OPT_LAX_KP 
OPT_PROCESS 
OPT_NO_KP 
OPT_NO_ST 
OPT_KP_OVERRIDE 
OPT_EXTRAPULSES 
OPT_SKIP 
OPT_INDICATION 
OPT_NOANSWER 

Definition at line 232 of file app_mf.c.

232  {
233  OPT_DELAY = (1 << 0),
234  OPT_MUTE = (1 << 1),
235  OPT_QUELCH = (1 << 2),
236  OPT_RELAXED = (1 << 3),
237  OPT_LAX_KP = (1 << 4),
238  OPT_PROCESS = (1 << 5),
239  OPT_NO_KP = (1 << 6),
240  OPT_NO_ST = (1 << 7),
241  OPT_KP_OVERRIDE = (1 << 8),
242  OPT_EXTRAPULSES = (1 << 9),
243 };

Function Documentation

◆ AST_MODULE_INFO_STANDARD_EXTENDED()

AST_MODULE_INFO_STANDARD_EXTENDED ( ASTERISK_GPL_KEY  ,
"MF Sender and Receiver Applications"   
)

Referenced by load_module().

◆ load_module()

static int load_module ( void  )
static

Definition at line 735 of file app_mf.c.

References ast_manager_register_xml, AST_MODULE_INFO_STANDARD_EXTENDED(), ast_register_application_xml, ASTERISK_GPL_KEY, EVENT_FLAG_CALL, manager_play_mf(), read_mf_exec(), read_sf_exec(), and sendmf_exec().

736 {
737  int res;
738 
743 
744  return res;
745 }
#define EVENT_FLAG_CALL
Definition: manager.h:72
static char * readmf_name
Definition: app_mf.c:258
static char * readsf_name
Definition: app_mf.c:259
static int read_mf_exec(struct ast_channel *chan, const char *data)
Definition: app_mf.c:551
static int sendmf_exec(struct ast_channel *chan, const char *vdata)
Definition: app_mf.c:620
static int read_sf_exec(struct ast_channel *chan, const char *data)
Definition: app_mf.c:472
static int manager_play_mf(struct mansession *s, const struct message *m)
Definition: app_mf.c:682
static const char sendmf_name[]
Definition: app_mf.c:260
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ manager_play_mf()

static int manager_play_mf ( struct mansession s,
const struct message m 
)
static

Definition at line 682 of file app_mf.c.

References ast_channel_get_by_name(), ast_channel_unref, ast_mf_stream(), ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), digit, MF_DURATION, MF_KP_DURATION, MF_ST_DURATION, and NULL.

Referenced by load_module().

683 {
684  const char *channel = astman_get_header(m, "Channel");
685  const char *digit = astman_get_header(m, "Digit");
686  const char *duration = astman_get_header(m, "Duration");
687  struct ast_channel *chan;
688  unsigned int duration_ms = MF_DURATION;
689 
690  if (!(chan = ast_channel_get_by_name(channel))) {
691  astman_send_error(s, m, "Channel not found");
692  return 0;
693  }
694 
695  if (ast_strlen_zero(digit)) {
696  astman_send_error(s, m, "No digit specified");
697  chan = ast_channel_unref(chan);
698  return 0;
699  }
700 
701  /* Override default duration with KP or ST-specific default durations */
702  if (!strcmp(digit, "*"))
703  duration_ms = MF_KP_DURATION;
704 
705  if (!strcmp(digit, "#") || !strcmp(digit, "A") || !strcmp(digit, "B") || !strcmp(digit, "C"))
706  duration_ms = MF_ST_DURATION;
707 
708  if (!ast_strlen_zero(duration) && (sscanf(duration, "%30u", &duration_ms) != 1)) {
709  astman_send_error(s, m, "Could not convert Duration parameter");
710  chan = ast_channel_unref(chan);
711  return 0;
712  }
713 
714  ast_mf_stream(chan, NULL, digit, 0, duration_ms, duration_ms, duration_ms, 1);
715 
716  chan = ast_channel_unref(chan);
717 
718  astman_send_ack(s, m, "MF successfully queued");
719 
720  return 0;
721 }
char digit
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
Definition: muted.c:95
#define MF_DURATION
Definition: app_mf.c:263
#define MF_KP_DURATION
Definition: app_mf.c:264
#define NULL
Definition: resample.c:96
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define MF_ST_DURATION
Definition: app_mf.c:265
int ast_mf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration, unsigned int durationkp, unsigned int durationst, int is_external)
Send a string of MF digits to a channel.
Definition: main/app.c:967
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

◆ read_mf_digits()

static int read_mf_digits ( struct ast_channel chan,
char *  buf,
int  timeout,
int  features,
int  laxkp,
int  override,
int  no_kp,
int  no_st 
)
static

Detects MF digits on channel using DSP, terminated by ST, STP, ST2P, or ST3P.

Returns
0 if successful, -1 if unsuccessful.
Parameters
chanchannel on which to read digits
strbuffer in which to store digits
timeoutms to wait for all digits before giving up

Definition at line 274 of file app_mf.c.

References ast_channel_name(), ast_debug, ast_dsp_free(), ast_dsp_new(), ast_dsp_process(), ast_dsp_set_digitmode(), ast_dsp_set_features(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log, ast_read(), ast_remaining_ms(), ast_tvnow(), ast_waitfor(), buf, DSP_DIGITMODE_MF, DSP_FEATURE_DIGIT_DETECT, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, NULL, pbx_builtin_setvar_helper(), result, str, ast_frame::subclass, and timeout.

Referenced by read_mf_exec().

274  {
275  struct ast_dsp *dsp;
276  struct ast_frame *frame = NULL;
277  struct timeval start;
278  int remaining_time = timeout;
279  int digits_read = 0;
280  int is_start_digit = 0;
281  char *str = buf;
282 
283  if (!(dsp = ast_dsp_new())) {
284  ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
285  pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "ERROR");
286  return -1;
287  }
289  ast_dsp_set_digitmode(dsp, DSP_DIGITMODE_MF | features);
290 
291  start = ast_tvnow();
292  *str = 0; /* start with empty output buffer */
293 
294  /* based on app_read and generic_fax_exec from res_fax */
295  while (timeout == 0 || remaining_time > 0) {
296  if (timeout > 0) {
297  remaining_time = ast_remaining_ms(start, timeout);
298  if (remaining_time <= 0) {
299  pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "TIMEOUT");
300  break;
301  }
302  }
303  /* ast_waitfordigit only waits for DTMF frames, we need to do DSP on voice frames */
304  if (ast_waitfor(chan, 1000) > 0) {
305  frame = ast_read(chan);
306  if (!frame) {
307  ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
308  pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "HANGUP");
309  break;
310  } else if (frame->frametype == AST_FRAME_VOICE) {
311  frame = ast_dsp_process(chan, dsp, frame);
312  /* AST_FRAME_DTMF is used all over the DSP code for DTMF, MF, fax, etc.
313  It's used because we can use the frame to store the digit detected.
314  All this means is that we received something we care about. */
315  if (frame->frametype == AST_FRAME_DTMF) {
316  char result = frame->subclass.integer;
317  if (digits_read == 0 && !laxkp && result != '*') {
318  ast_debug(1, "Received MF digit, but no KP yet, ignoring: %c\n", result);
319  continue;
320  }
321  ast_debug(1, "Received MF digit: %c\n", result);
322  digits_read++;
323  if (result == '*') {
324  /* We received an additional KP, start over? */
325  if (override && digits_read > 0) {
326  ast_debug(1, "Received another KP, starting over\n");
327  str = buf;
328  *str = 0;
329  digits_read = 1; /* we just detected a KP */
330  }
331  /* if we were told not to include the ST digit in the output string, then skip it */
332  if (no_kp) {
333  continue;
334  }
335  }
336  is_start_digit = (strchr("#", result) || strchr("A", result) || strchr("B", result) || strchr("C", result));
337  /* if we were told not to include the ST digit in the output string, then skip it */
338  if (!no_st || !is_start_digit) {
339  *str++ = result;
340  *str = 0;
341  }
342  /* we received a ST digit (ST, STP, ST2P, or ST3P), so we're done */
343  if (is_start_digit) {
344  pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "START");
345  break;
346  }
347  }
348  }
349  } else {
350  pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "HANGUP");
351  }
352  }
353  ast_dsp_free(dsp);
354  ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
355  return 0;
356 }
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress...
Definition: dsp.c:1494
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
#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 timeout
Definition: cdr_mysql.c:86
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
#define AST_FRAME_DTMF
struct ast_frame_subclass subclass
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
Definition: dsp.c:405
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: main/utils.c:2033
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1755
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_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
const char * ast_channel_name(const struct ast_channel *chan)
static PGresult * result
Definition: cel_pgsql.c:88
Data structure associated with a single frame of data.
enum ast_frame_type frametype
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
Definition: dsp.c:1844

◆ read_mf_exec()

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

Definition at line 551 of file app_mf.c.

References AST_APP_ARG, ast_app_parse_options(), AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, ast_test_flag, ast_verb, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_NOQUELCH, DSP_DIGITMODE_RELAXDTMF, LOG_WARNING, NULL, OPT_DELAY, OPT_KP_OVERRIDE, OPT_LAX_KP, OPT_MUTE, OPT_NO_KP, OPT_NO_ST, OPT_QUELCH, OPT_RELAXED, options, pbx_builtin_setvar_helper(), read_app_options, read_mf_digits(), timeout, and tmp().

Referenced by load_module().

552 {
553  char tmp[256] = "";
554  int to = 0;
555  double tosec;
556  struct ast_flags flags = {0};
557  char *argcopy = NULL;
558  int features = 0;
559 
560  AST_DECLARE_APP_ARGS(arglist,
561  AST_APP_ARG(variable);
564  );
565 
566  if (ast_strlen_zero(data)) {
567  ast_log(LOG_WARNING, "ReceiveMF requires an argument (variable)\n");
568  return -1;
569  }
570 
571  argcopy = ast_strdupa(data);
572 
573  AST_STANDARD_APP_ARGS(arglist, argcopy);
574 
575  if (!ast_strlen_zero(arglist.options)) {
576  ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
577  }
578 
579  if (!ast_strlen_zero(arglist.timeout)) {
580  tosec = atof(arglist.timeout);
581  if (tosec <= 0) {
582  to = 0;
583  } else {
584  to = tosec * 1000.0;
585  }
586  }
587 
588  if (ast_strlen_zero(arglist.variable)) {
589  ast_log(LOG_WARNING, "Invalid! Usage: ReceiveMF(variable[,timeout][,option])\n");
590  return -1;
591  }
592 
593  if (ast_test_flag(&flags, OPT_DELAY)) {
594  features |= DSP_DIGITMODE_MUTEMAX;
595  }
596 
597  if (ast_test_flag(&flags, OPT_MUTE)) {
598  features |= DSP_DIGITMODE_MUTECONF;
599  }
600 
601  if (!ast_test_flag(&flags, OPT_QUELCH)) {
602  features |= DSP_DIGITMODE_NOQUELCH;
603  }
604 
605  if (ast_test_flag(&flags, OPT_RELAXED)) {
606  features |= DSP_DIGITMODE_RELAXDTMF;
607  }
608 
609  read_mf_digits(chan, tmp, to, features, (ast_test_flag(&flags, OPT_LAX_KP)),
610  (ast_test_flag(&flags, OPT_KP_OVERRIDE)), (ast_test_flag(&flags, OPT_NO_KP)), (ast_test_flag(&flags, OPT_NO_ST)));
611  pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
612  if (!ast_strlen_zero(tmp)) {
613  ast_verb(3, "MF digits received: '%s'\n", tmp);
614  } else {
615  ast_verb(3, "No MF digits received.\n");
616  }
617  return 0;
618 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define DSP_DIGITMODE_MUTECONF
Definition: dsp.h:35
#define LOG_WARNING
Definition: logger.h:274
static int timeout
Definition: cdr_mysql.c:86
static int tmp()
Definition: bt_open.c:389
unsigned int flags
Definition: utils.h:200
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
static const struct ast_app_option read_app_options[128]
Definition: app_mf.c:256
#define DSP_DIGITMODE_RELAXDTMF
Definition: dsp.h:37
#define ast_log
Definition: astobj2.c:42
static int read_mf_digits(struct ast_channel *chan, char *buf, int timeout, int features, int laxkp, int override, int no_kp, int no_st)
Detects MF digits on channel using DSP, terminated by ST, STP, ST2P, or ST3P.
Definition: app_mf.c:274
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
#define DSP_DIGITMODE_MUTEMAX
Definition: dsp.h:36
Structure used to handle boolean flags.
Definition: utils.h:199
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...
#define DSP_DIGITMODE_NOQUELCH
Definition: dsp.h:34
static struct test_options options
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ read_sf_digits()

static int read_sf_digits ( struct ast_channel chan,
char *  buf,
int  timeout,
int  maxdigits,
int  freq,
int  features,
int  extrapulses 
)
static

Definition at line 358 of file app_mf.c.

References ast_channel_name(), ast_debug, ast_dsp_free(), ast_dsp_new(), ast_dsp_process(), ast_dsp_set_features(), ast_dsp_set_freqmode(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log, ast_read(), ast_remaining_ms(), ast_tvnow(), ast_waitfor(), buf, DSP_FEATURE_FREQ_DETECT, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, NULL, pbx_builtin_setvar_helper(), result, str, ast_frame::subclass, and timeout.

Referenced by read_sf_exec().

358  {
359  struct ast_dsp *dsp;
360  struct ast_frame *frame = NULL;
361  struct timeval start, pulsetimer, digittimer;
362  int remaining_time = timeout;
363  char *str = buf;
364  int hits = 0, digits_read = 0;
365  unsigned short int sf_on = 0;
366 
367  if (!(dsp = ast_dsp_new())) {
368  ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
369  pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "ERROR");
370  return -1;
371  }
373  ast_dsp_set_freqmode(dsp, freq, 60, 16, 0);
374 
375  start = ast_tvnow();
376  *str = 0; /* start with empty output buffer */
377 
378  while (timeout == 0 || remaining_time > 0) {
379  if (timeout > 0) {
380  remaining_time = ast_remaining_ms(start, timeout);
381  if (remaining_time <= 0) {
382  pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "TIMEOUT");
383  break;
384  }
385  }
386  if (ast_waitfor(chan, 1000) > 0) {
387  frame = ast_read(chan);
388  if (!frame) {
389  ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
390  pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "HANGUP");
391  break;
392  } else if (frame->frametype == AST_FRAME_VOICE) {
393  frame = ast_dsp_process(chan, dsp, frame);
394  if (frame->frametype == AST_FRAME_DTMF) {
395  char result = frame->subclass.integer;
396  if (result == 'q') {
397  sf_on = 1;
398  pulsetimer = ast_tvnow(); /* reset the pulse timer */
399  /* now, we need at least a 40ms pause to register the pulse */
400  }
401  } else {
402  if (sf_on) {
403  int timeleft = ast_remaining_ms(pulsetimer, 40);
404  if (timeleft <= 0) {
405  sf_on = 0;
406  /* The pulse needs to end no more than 75ms after we detected it */
407  if (timeleft > -75) {
408  hits++;
409  digittimer = ast_tvnow(); /* reset the digit timer */
410  ast_debug(5, "Detected SF pulse (pulse #%d)\n", hits);
411  } else {
412  ast_debug(5, "SF noise, ignoring, time elapsed was %d ms\n", timeleft);
413  }
414  }
415  } else if (hits > 0 && ast_remaining_ms(digittimer, 100) <= 0) {
416  /* has the digit finished? */
417  ast_debug(2, "Received SF digit: %d\n", hits);
418  digits_read++;
419  if (hits > 10) {
420  if (extrapulses) {
421  /* dahdi-base.c translates 11 to * and 12 to # */
422  if (hits == 11)
423  hits = '*';
424  else if (hits == 12)
425  hits = '#';
426  else if (hits == 13)
427  hits = 'D';
428  else if (hits == 14)
429  hits = 'C';
430  else if (hits == 15)
431  hits = 'B';
432  else if (hits == 16)
433  hits = 'A';
434  else {
435  ast_debug(3, "Got SF pulse digit %d, is someone playing with the phone?\n", hits);
436  hits = 'A';
437  }
438  *str++ = hits;
439  } else {
440  ast_debug(2, "Got more than 10 pulses, truncating to 10\n");
441  hits = 0; /* 10 dial pulses = digit 0 */
442  *str++ = hits + '0';
443  }
444  } else {
445  if (hits == 10) {
446  hits = 0; /* 10 dial pulses = digit 0 */
447  }
448  *str++ = hits + '0';
449  }
450  *str = 0;
451  hits = 0;
452  if (maxdigits > 0 && digits_read >= maxdigits) {
453  pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "START");
454  break;
455  }
456  }
457  }
458  }
459  } else {
460  pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "HANGUP");
461  }
462  }
463  ast_dsp_free(dsp);
464  ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
465  return 0;
466 }
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress...
Definition: dsp.c:1494
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#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 timeout
Definition: cdr_mysql.c:86
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
#define AST_FRAME_DTMF
struct ast_frame_subclass subclass
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
Definition: dsp.c:405
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: main/utils.c:2033
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1755
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_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
const char * ast_channel_name(const struct ast_channel *chan)
static PGresult * result
Definition: cel_pgsql.c:88
Data structure associated with a single frame of data.
int ast_dsp_set_freqmode(struct ast_dsp *dsp, int freq1, int dur, int db, int squelch)
Set arbitrary frequency detection mode.
Definition: dsp.c:1859
enum ast_frame_type frametype
#define DSP_FEATURE_FREQ_DETECT
Definition: dsp.h:45

◆ read_sf_exec()

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

Definition at line 472 of file app_mf.c.

References AST_APP_ARG, ast_app_parse_options(), AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_str_to_int(), ast_strdupa, ast_strlen_zero, ast_test_flag, ast_verb, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_NOQUELCH, DSP_DIGITMODE_RELAXDTMF, LOG_WARNING, NULL, OPT_DELAY, OPT_EXTRAPULSES, OPT_MUTE, OPT_QUELCH, OPT_RELAXED, options, pbx_builtin_setvar_helper(), read_app_options, read_sf_digits(), timeout, and tmp().

Referenced by load_module().

473 {
474  char tmp[256] = "";
475  double tosec;
476  struct ast_flags flags = {0};
477  char *argcopy = NULL;
478  int features = 0, digits = 0, to = 0, freq = 2600;
479 
480  AST_DECLARE_APP_ARGS(arglist,
481  AST_APP_ARG(variable);
482  AST_APP_ARG(digits);
484  AST_APP_ARG(freq);
486  );
487 
488  if (ast_strlen_zero(data)) {
489  ast_log(LOG_WARNING, "ReceiveSF requires an argument (variable)\n");
490  return -1;
491  }
492 
493  argcopy = ast_strdupa(data);
494 
495  AST_STANDARD_APP_ARGS(arglist, argcopy);
496 
497  if (!ast_strlen_zero(arglist.options)) {
498  ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
499  }
500 
501  if (!ast_strlen_zero(arglist.timeout)) {
502  tosec = atof(arglist.timeout);
503  if (tosec <= 0) {
504  to = 0;
505  } else {
506  to = tosec * 1000.0;
507  }
508  }
509 
510  if (!ast_strlen_zero(arglist.digits) && (ast_str_to_int(arglist.digits, &digits) || digits <= 0)) {
511  ast_log(LOG_WARNING, "Invalid number of digits: %s\n", arglist.digits);
512  return -1;
513  }
514 
515  if (!ast_strlen_zero(arglist.freq) && (ast_str_to_int(arglist.freq, &freq) || freq <= 0)) {
516  ast_log(LOG_WARNING, "Invalid freq: %s\n", arglist.freq);
517  return -1;
518  }
519 
520  if (ast_strlen_zero(arglist.variable)) {
521  ast_log(LOG_WARNING, "Invalid! Usage: ReceiveSF(variable[,timeout][,option])\n");
522  return -1;
523  }
524 
525  if (ast_test_flag(&flags, OPT_DELAY)) {
526  features |= DSP_DIGITMODE_MUTEMAX;
527  }
528 
529  if (ast_test_flag(&flags, OPT_MUTE)) {
530  features |= DSP_DIGITMODE_MUTECONF;
531  }
532 
533  if (!ast_test_flag(&flags, OPT_QUELCH)) {
534  features |= DSP_DIGITMODE_NOQUELCH;
535  }
536 
537  if (ast_test_flag(&flags, OPT_RELAXED)) {
538  features |= DSP_DIGITMODE_RELAXDTMF;
539  }
540 
541  read_sf_digits(chan, tmp, to, digits, freq, features, ast_test_flag(&flags, OPT_EXTRAPULSES));
542  pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
543  if (!ast_strlen_zero(tmp)) {
544  ast_verb(3, "MF digits received: '%s'\n", tmp);
545  } else {
546  ast_verb(3, "No MF digits received.\n");
547  }
548  return 0;
549 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define DSP_DIGITMODE_MUTECONF
Definition: dsp.h:35
#define LOG_WARNING
Definition: logger.h:274
static int timeout
Definition: cdr_mysql.c:86
static int tmp()
Definition: bt_open.c:389
unsigned int flags
Definition: utils.h:200
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
static const struct ast_app_option read_app_options[128]
Definition: app_mf.c:256
#define DSP_DIGITMODE_RELAXDTMF
Definition: dsp.h:37
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
int ast_str_to_int(const char *str, int *res)
Convert the given string to a signed integer.
Definition: conversions.c:44
#define DSP_DIGITMODE_MUTEMAX
Definition: dsp.h:36
static int read_sf_digits(struct ast_channel *chan, char *buf, int timeout, int maxdigits, int freq, int features, int extrapulses)
Definition: app_mf.c:358
Structure used to handle boolean flags.
Definition: utils.h:199
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...
#define DSP_DIGITMODE_NOQUELCH
Definition: dsp.h:34
static struct test_options options
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ sendmf_exec()

static int sendmf_exec ( struct ast_channel chan,
const char *  vdata 
)
static

Definition at line 620 of file app_mf.c.

References args, AST_APP_ARG, ast_app_parse_timelen(), ast_channel_get_by_name(), ast_channel_unref, AST_DECLARE_APP_ARGS, ast_log, ast_mf_stream(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, LOG_WARNING, MF_BETWEEN_MS, MF_DURATION, MF_KP_DURATION, MF_ST_DURATION, NULL, and TIMELEN_MILLISECONDS.

Referenced by load_module().

621 {
622  int res;
623  char *data;
624  int dinterval = 0, duration = 0, durationkp = 0, durationst = 0;
625  struct ast_channel *chan_found = NULL;
626  struct ast_channel *chan_dest = chan;
627  struct ast_channel *chan_autoservice = NULL;
629  AST_APP_ARG(digits);
630  AST_APP_ARG(dinterval);
631  AST_APP_ARG(duration);
632  AST_APP_ARG(durationkp);
633  AST_APP_ARG(durationst);
635  );
636 
637  if (ast_strlen_zero(vdata)) {
638  ast_log(LOG_WARNING, "SendMF requires an argument\n");
639  return 0;
640  }
641 
642  data = ast_strdupa(vdata);
644 
645  if (ast_strlen_zero(args.digits)) {
646  ast_log(LOG_WARNING, "The digits argument is required (0-9,*#ABC,wf)\n");
647  return 0;
648  }
649  if (!ast_strlen_zero(args.dinterval)) {
650  ast_app_parse_timelen(args.dinterval, &dinterval, TIMELEN_MILLISECONDS);
651  }
652  if (!ast_strlen_zero(args.duration)) {
653  ast_app_parse_timelen(args.duration, &duration, TIMELEN_MILLISECONDS);
654  }
655  if (!ast_strlen_zero(args.durationkp)) {
656  ast_app_parse_timelen(args.durationkp, &durationkp, TIMELEN_MILLISECONDS);
657  }
658  if (!ast_strlen_zero(args.durationst)) {
659  ast_app_parse_timelen(args.durationst, &durationst, TIMELEN_MILLISECONDS);
660  }
661  if (!ast_strlen_zero(args.channel)) {
662  chan_found = ast_channel_get_by_name(args.channel);
663  if (!chan_found) {
664  ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
665  return 0;
666  }
667  chan_dest = chan_found;
668  if (chan_found != chan) {
669  chan_autoservice = chan;
670  }
671  }
672  res = ast_mf_stream(chan_dest, chan_autoservice, args.digits, dinterval <= 0 ? MF_BETWEEN_MS : dinterval,
673  duration <= 0 ? MF_DURATION : duration, durationkp <= 0 ? MF_KP_DURATION : durationkp,
674  durationst <= 0 ? MF_ST_DURATION : durationst, 0);
675  if (chan_found) {
676  ast_channel_unref(chan_found);
677  }
678 
679  return chan_autoservice ? 0 : res;
680 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define MF_BETWEEN_MS
Definition: app_mf.c:262
#define LOG_WARNING
Definition: logger.h:274
Definition: muted.c:95
const char * args
#define MF_DURATION
Definition: app_mf.c:263
#define MF_KP_DURATION
Definition: app_mf.c:264
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define MF_ST_DURATION
Definition: app_mf.c:265
int ast_mf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration, unsigned int durationkp, unsigned int durationst, int is_external)
Send a string of MF digits to a channel.
Definition: main/app.c:967
int ast_app_parse_timelen(const char *timestr, int *result, enum ast_timelen defunit)
Common routine to parse time lengths, with optional time unit specifier.
Definition: main/app.c:3113
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 723 of file app_mf.c.

References ast_manager_unregister(), and ast_unregister_application().

724 {
725  int res;
726 
730  res |= ast_manager_unregister("PlayMF");
731 
732  return res;
733 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static char * readmf_name
Definition: app_mf.c:258
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
static char * readsf_name
Definition: app_mf.c:259
static const char sendmf_name[]
Definition: app_mf.c:260

Variable Documentation

◆ read_app_options

const struct ast_app_option read_app_options[128] = { [ 'd' ] = { .flag = OPT_DELAY }, [ 'e' ] = { .flag = OPT_EXTRAPULSES }, [ 'l' ] = { .flag = OPT_LAX_KP }, [ 'k' ] = { .flag = OPT_NO_KP }, [ 'm' ] = { .flag = OPT_MUTE }, [ 'o' ] = { .flag = OPT_KP_OVERRIDE }, [ 'p' ] = { .flag = OPT_PROCESS }, [ 'q' ] = { .flag = OPT_QUELCH }, [ 'r' ] = { .flag = OPT_RELAXED }, [ 's' ] = { .flag = OPT_NO_ST }, }
static

Definition at line 256 of file app_mf.c.

Referenced by read_mf_exec(), and read_sf_exec().

◆ readmf_name

char* readmf_name = "ReceiveMF"
static

Definition at line 258 of file app_mf.c.

◆ readsf_name

char* readsf_name = "ReceiveSF"
static

Definition at line 259 of file app_mf.c.

◆ sendmf_name

const char sendmf_name[] = "SendMF"
static

Definition at line 260 of file app_mf.c.