Asterisk - The Open Source Telephony Project  21.4.1
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"

Go to the source code of this file.

Macros

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

Enumerations

enum  { OPT_ARG_MAXDIGITS, OPT_ARG_ARRAY_SIZE }
 
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_MAXDIGITS = (1 << 9), OPT_SKIP = (1 << 0), OPT_INDICATION = (1 << 1),
  OPT_NOANSWER = (1 << 2), OPT_TERMINATOR = (1 << 3), OPT_KEEP_TERMINATOR = (1 << 4), OPT_ANSWER = (1 << 0),
  OPT_DELAY = (1 << 0), OPT_MUTE = (1 << 1), OPT_QUELCH = (1 << 2), OPT_RELAXED = (1 << 3),
  OPT_EXTRAPULSES = (1 << 4)
}
 

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 buflen, int timeout, int features, int laxkp, int override, int no_kp, int no_st, int maxdigits)
 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 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 }, [ 'l' ] = { .flag = OPT_LAX_KP }, [ 'k' ] = { .flag = OPT_NO_KP }, [ 'm' ] = { .flag = OPT_MUTE }, [ 'n' ] = { .flag = OPT_MAXDIGITS , .arg_index = OPT_ARG_MAXDIGITS + 1 }, [ 'o' ] = { .flag = OPT_KP_OVERRIDE }, [ 'p' ] = { .flag = OPT_PROCESS }, [ 'q' ] = { .flag = OPT_QUELCH }, [ 'r' ] = { .flag = OPT_RELAXED }, [ 's' ] = { .flag = OPT_NO_ST }, }
 
static const char * readmf_name = "ReceiveMF"
 
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.

Function Documentation

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

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

Parameters
chanchannel on which to read digits
bufBuffer in which to store digits
buflenSize of buffer
timeoutms to wait for all digits before giving up
featuresAny additional DSP features to use
laxkpReceive digits even if KP not received
overrideStart over if we receive additional KPs
no_kpDon't include KP in the output
no_stDon't include start digits in the output
maxdigitsIf greater than 0, only read this many digits no matter what
Return values
0if successful
-1if unsuccessful (including hangup).

Definition at line 247 of file app_mf.c.

References ast_debug, ast_dsp_new(), ast_dsp_process(), ast_dsp_set_digitmode(), ast_dsp_set_features(), AST_FRAME_VOICE, ast_read(), ast_remaining_ms(), ast_tvnow(), ast_waitfor(), DSP_DIGITMODE_MF, ast_frame::frametype, ast_frame_subclass::integer, pbx_builtin_setvar_helper(), and ast_frame::subclass.

247  {
248  struct ast_dsp *dsp;
249  struct ast_frame *frame = NULL;
250  struct timeval start;
251  int remaining_time = timeout;
252  int digits_read = 0;
253  int is_start_digit = 0;
254  char *str = buf;
255  int res = 0;
256 
257  if (!(dsp = ast_dsp_new())) {
258  ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
259  pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "ERROR");
260  return -1;
261  }
262  ast_dsp_set_features(dsp, DSP_FEATURE_DIGIT_DETECT);
263  ast_dsp_set_digitmode(dsp, DSP_DIGITMODE_MF | features);
264 
265  start = ast_tvnow();
266  *str = 0; /* start with empty output buffer */
267 
268  /* based on app_read and generic_fax_exec from res_fax */
269  while (timeout == 0 || remaining_time > 0) {
270  if (timeout > 0) {
271  remaining_time = ast_remaining_ms(start, timeout);
272  if (remaining_time <= 0) {
273  pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "TIMEOUT");
274  break;
275  }
276  }
277  if ((maxdigits && digits_read >= maxdigits) || digits_read >= (buflen - 1)) { /* we don't have room to store any more digits (very unlikely to happen for a legitimate reason) */
278  /* This result will probably not be usable, so status should not be START */
279  pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "MAXDIGITS");
280  break;
281  }
282  /* ast_waitfordigit only waits for DTMF frames, we need to do DSP on voice frames */
283  if (ast_waitfor(chan, 1000) > 0) {
284  frame = ast_read(chan);
285  if (!frame) {
286  ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
287  pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "HANGUP");
288  break;
289  } else if (frame->frametype == AST_FRAME_VOICE) {
290  frame = ast_dsp_process(chan, dsp, frame);
291  /* AST_FRAME_DTMF is used all over the DSP code for DTMF, MF, fax, etc.
292  It's used because we can use the frame to store the digit detected.
293  All this means is that we received something we care about. */
294  if (frame->frametype == AST_FRAME_DTMF) {
295  char result = frame->subclass.integer;
296  if (digits_read == 0 && !laxkp && result != '*') {
297  ast_debug(1, "Received MF digit, but no KP yet, ignoring: %c\n", result);
298  ast_frfree(frame);
299  continue;
300  }
301  ast_debug(1, "Received MF digit: %c\n", result);
302  if (result == '*') {
303  /* We received an additional KP, start over? */
304  if (override && digits_read > 0) {
305  ast_debug(1, "Received another KP, starting over\n");
306  str = buf;
307  *str = 0;
308  digits_read = 1; /* we just detected a KP */
309  } else {
310  digits_read++;
311  }
312  /* if we were told not to include the KP digit in the output string, then skip it */
313  if (no_kp) {
314  ast_frfree(frame);
315  continue;
316  }
317  } else {
318  digits_read++;
319  }
320  is_start_digit = (strchr("#", result) || strchr("A", result) || strchr("B", result) || strchr("C", result));
321  /* if we were told not to include the ST digit in the output string, then skip it */
322  if (!no_st || !is_start_digit) {
323  *str++ = result; /* won't write past allotted memory, because of buffer check at top of loop */
324  *str = 0;
325  }
326  /* we received a ST digit (ST, STP, ST2P, or ST3P), so we're done */
327  if (is_start_digit) {
328  pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "START");
329  ast_frfree(frame);
330  break;
331  }
332  /* only free frame if it was a DSP match. The MF itself should not be muted. */
333  ast_frfree(frame);
334  }
335  }
336  } else {
337  pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "HANGUP");
338  res = -1;
339  }
340  }
341  ast_dsp_free(dsp);
342  ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
343  return res;
344 }
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:1499
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4257
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct ast_frame_subclass subclass
Definition: dsp.c:407
#define ast_debug(level,...)
Log a DEBUG message.
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2281
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1768
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:3162
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:1857