190 enum read_option_flags {
191 OPT_DELAY = (1 << 0),
193 OPT_QUELCH = (1 << 2),
194 OPT_RELAXED = (1 << 3),
195 OPT_LAX_KP = (1 << 4),
196 OPT_PROCESS = (1 << 5),
197 OPT_NO_KP = (1 << 6),
198 OPT_NO_ST = (1 << 7),
199 OPT_KP_OVERRIDE = (1 << 8),
200 OPT_MAXDIGITS = (1 << 9),
222 static const char *readmf_name =
"ReceiveMF";
223 static const char sendmf_name[] =
"SendMF";
225 #define MF_BETWEEN_MS 50
226 #define MF_DURATION 55
227 #define MF_KP_DURATION 120
228 #define MF_ST_DURATION 65
247 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) {
250 struct timeval start;
251 int remaining_time = timeout;
253 int is_start_digit = 0;
258 ast_log(LOG_WARNING,
"Unable to allocate DSP!\n");
269 while (timeout == 0 || remaining_time > 0) {
272 if (remaining_time <= 0) {
277 if ((maxdigits && digits_read >= maxdigits) || digits_read >= (buflen - 1)) {
286 ast_debug(1,
"Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
294 if (frame->
frametype == AST_FRAME_DTMF) {
296 if (digits_read == 0 && !laxkp && result !=
'*') {
297 ast_debug(1,
"Received MF digit, but no KP yet, ignoring: %c\n", result);
301 ast_debug(1,
"Received MF digit: %c\n", result);
304 if (
override && digits_read > 0) {
305 ast_debug(1,
"Received another KP, starting over\n");
320 is_start_digit = (strchr(
"#", result) || strchr(
"A", result) || strchr(
"B", result) || strchr(
"C", result));
322 if (!no_st || !is_start_digit) {
327 if (is_start_digit) {
342 ast_debug(3,
"channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
346 static int read_mf_exec(
struct ast_channel *chan,
const char *data)
348 #define BUFFER_SIZE 256
349 char tmp[BUFFER_SIZE] =
"";
353 char *optargs[OPT_ARG_ARRAY_SIZE];
354 char *argcopy = NULL;
355 int res, features = 0, maxdigits = 0;
363 if (ast_strlen_zero(data)) {
364 ast_log(LOG_WARNING,
"ReceiveMF requires an argument (variable)\n");
372 if (!ast_strlen_zero(arglist.options)) {
376 if (!ast_strlen_zero(arglist.timeout)) {
377 tosec = atof(arglist.timeout);
385 if (ast_strlen_zero(arglist.variable)) {
386 ast_log(LOG_WARNING,
"Invalid! Usage: ReceiveMF(variable[,timeout][,option])\n");
389 if (ast_test_flag(&flags, OPT_MAXDIGITS) && !ast_strlen_zero(optargs[OPT_ARG_MAXDIGITS])) {
390 maxdigits = atoi(optargs[OPT_ARG_MAXDIGITS]);
391 if (maxdigits <= 0) {
392 ast_log(LOG_WARNING,
"Invalid maximum number of digits, ignoring: '%s'\n", optargs[OPT_ARG_MAXDIGITS]);
397 if (ast_test_flag(&flags, OPT_DELAY)) {
401 if (ast_test_flag(&flags, OPT_MUTE)) {
405 if (!ast_test_flag(&flags, OPT_QUELCH)) {
409 if (ast_test_flag(&flags, OPT_RELAXED)) {
413 res =
read_mf_digits(chan, tmp, BUFFER_SIZE, to, features, (ast_test_flag(&flags, OPT_LAX_KP)),
414 (ast_test_flag(&flags, OPT_KP_OVERRIDE)), (ast_test_flag(&flags, OPT_NO_KP)), (ast_test_flag(&flags, OPT_NO_ST)), maxdigits);
416 if (!ast_strlen_zero(tmp)) {
417 ast_verb(3,
"MF digits received: '%s'\n", tmp);
419 ast_verb(3,
"No MF digits received.\n");
424 static int sendmf_exec(
struct ast_channel *chan,
const char *vdata)
428 int dinterval = 0, duration = 0, durationkp = 0, durationst = 0;
441 if (ast_strlen_zero(vdata)) {
442 ast_log(LOG_WARNING,
"SendMF requires an argument\n");
449 if (ast_strlen_zero(args.digits)) {
450 ast_log(LOG_WARNING,
"The digits argument is required (0-9,*#ABC,wf)\n");
453 if (!ast_strlen_zero(args.dinterval)) {
456 if (!ast_strlen_zero(args.duration)) {
459 if (!ast_strlen_zero(args.durationkp)) {
462 if (!ast_strlen_zero(args.durationst)) {
465 if (!ast_strlen_zero(args.channel)) {
468 ast_log(LOG_WARNING,
"No such channel: %s\n", args.channel);
471 chan_dest = chan_found;
472 if (chan_found != chan) {
473 chan_autoservice = chan;
476 res =
ast_mf_stream(chan_dest, chan_autoservice, NULL, args.digits, dinterval <= 0 ? MF_BETWEEN_MS : dinterval,
477 duration <= 0 ? MF_DURATION : duration, durationkp <= 0 ? MF_KP_DURATION : durationkp,
478 durationst <= 0 ? MF_ST_DURATION : durationst, 0);
481 return chan_autoservice ? 0 : res;
490 unsigned int duration_ms = MF_DURATION;
497 if (ast_strlen_zero(digit)) {
504 if (!strcmp(digit,
"*"))
505 duration_ms = MF_KP_DURATION;
507 if (!strcmp(digit,
"#") || !strcmp(digit,
"A") || !strcmp(digit,
"B") || !strcmp(digit,
"C"))
508 duration_ms = MF_ST_DURATION;
510 if (!ast_strlen_zero(duration) && (sscanf(duration,
"%30u", &duration_ms) != 1)) {
516 ast_mf_stream(chan, NULL, NULL, digit, 0, duration_ms, duration_ms, duration_ms, 1);
525 static int unload_module(
void)
536 static int load_module(
void)
547 AST_MODULE_INFO_STANDARD_EXTENDED(
ASTERISK_GPL_KEY,
"MF Sender and Receiver Applications");
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...
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_channel_unref(c)
Decrease channel reference count.
Convenient Signal Processing routines.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define DSP_DIGITMODE_MUTECONF
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
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.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int ast_unregister_application(const char *app)
Unregister an application.
struct ast_frame_subclass subclass
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define DSP_DIGITMODE_RELAXDTMF
General Asterisk PBX channel definitions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_channel_cleanup(c)
Cleanup a channel reference.
In case you didn't read that giant block of text above the mansession_session struct, the mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Conversion utility functions.
#define ast_debug(level,...)
Log a DEBUG message.
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.
Core PBX routines and definitions.
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
#define DSP_DIGITMODE_MUTEMAX
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Structure used to handle boolean flags.
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.
Data structure associated with a single frame of data.
enum ast_frame_type frametype
#define DSP_DIGITMODE_NOQUELCH
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
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.
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
#define ASTERISK_GPL_KEY
The text the key() function should return.
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
int ast_mf_stream(struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *chan2, 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.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Asterisk module definitions.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
#define AST_APP_ARG(name)
Define an application argument.