149 enum read_option_flags {
150 OPT_DELAY = (1 << 0),
152 OPT_QUELCH = (1 << 2),
153 OPT_RELAXED = (1 << 3),
154 OPT_EXTRAPULSES = (1 << 4),
165 static const char *readsf_name =
"ReceiveSF";
166 static const char sendsf_name[] =
"SendSF";
183 static int read_sf_digits(
struct ast_channel *chan,
char *buf,
int buflen,
int timeout,
int maxdigits,
int freq,
int features,
int extrapulses) {
185 #define SF_MIN_OFF 25
187 #define SF_BETWEEN 600
188 #define SF_MIN_DETECT 50
192 struct timeval start, pulsetimer, digittimer;
193 int remaining_time = timeout;
195 int hits = 0, digits_read = 0;
196 unsigned short int sf_on = 0;
200 ast_log(LOG_WARNING,
"Unable to allocate DSP!\n");
211 while (timeout == 0 || remaining_time > 0) {
214 if (remaining_time <= 0) {
219 if (digits_read >= (buflen - 1)) {
227 ast_debug(1,
"Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
232 if (frame->
frametype == AST_FRAME_DTMF) {
245 if (timeleft > -30) {
248 ast_debug(5,
"Detected SF pulse (pulse #%d)\n", hits);
251 ast_log(LOG_WARNING,
"Unable to allocate DSP!\n");
259 ast_debug(5,
"SF noise, ignoring, time elapsed was %d ms\n", timeleft);
264 ast_debug(2,
"Received SF digit: %d\n", hits);
271 }
else if (hits == 12) {
273 }
else if (hits == 13) {
275 }
else if (hits == 14) {
277 }
else if (hits == 15) {
279 }
else if (hits == 16) {
282 ast_debug(3,
"Got %d SF pulses, is someone playing with the phone?\n", hits);
287 ast_debug(2,
"Got more than 10 pulses, truncating to 10\n");
299 if (maxdigits > 0 && digits_read >= maxdigits) {
316 ast_debug(3,
"channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
320 static int read_sf_exec(
struct ast_channel *chan,
const char *data)
322 #define BUFFER_SIZE 256
323 char tmp[BUFFER_SIZE] =
"";
326 char *argcopy = NULL;
327 int res, features = 0, digits = 0, to = 0, freq = 2600;
337 if (ast_strlen_zero(data)) {
338 ast_log(LOG_WARNING,
"ReceiveSF requires an argument (variable)\n");
346 if (!ast_strlen_zero(arglist.options)) {
350 if (!ast_strlen_zero(arglist.timeout)) {
351 tosec = atof(arglist.timeout);
359 if (!ast_strlen_zero(arglist.digits) && (
ast_str_to_int(arglist.digits, &digits) || digits <= 0)) {
360 ast_log(LOG_WARNING,
"Invalid number of digits: %s\n", arglist.digits);
364 if (!ast_strlen_zero(arglist.freq) && (
ast_str_to_int(arglist.freq, &freq) || freq <= 0)) {
365 ast_log(LOG_WARNING,
"Invalid freq: %s\n", arglist.freq);
369 if (ast_strlen_zero(arglist.variable)) {
370 ast_log(LOG_WARNING,
"Invalid! Usage: ReceiveSF(variable[,timeout][,option])\n");
374 if (ast_test_flag(&flags, OPT_DELAY)) {
378 if (ast_test_flag(&flags, OPT_MUTE)) {
382 if (!ast_test_flag(&flags, OPT_QUELCH)) {
386 if (ast_test_flag(&flags, OPT_RELAXED)) {
390 res =
read_sf_digits(chan, tmp, BUFFER_SIZE, to, digits, freq, features, ast_test_flag(&flags, OPT_EXTRAPULSES));
392 if (!ast_strlen_zero(tmp)) {
393 ast_verb(3,
"SF digits received: '%s'\n", tmp);
395 ast_verb(3,
"No SF digits received.\n");
400 static int sendsf_exec(
struct ast_channel *chan,
const char *vdata)
404 int frequency = 2600;
414 if (ast_strlen_zero(vdata)) {
415 ast_log(LOG_WARNING,
"SendSF requires an argument\n");
422 if (ast_strlen_zero(args.digits)) {
423 ast_log(LOG_WARNING,
"The digits argument is required (0-9,wf)\n");
426 if (!ast_strlen_zero(args.frequency) && (
ast_str_to_int(args.frequency, &frequency) || frequency < 1)) {
427 ast_log(LOG_WARNING,
"Invalid duration: %s\n", args.frequency);
430 if (!ast_strlen_zero(args.channel)) {
433 ast_log(LOG_WARNING,
"No such channel: %s\n", args.channel);
436 chan_dest = chan_found;
437 if (chan_found != chan) {
438 chan_autoservice = chan;
441 res =
ast_sf_stream(chan_dest, chan_autoservice, NULL, args.digits, frequency, 0);
444 return chan_autoservice ? 0 : res;
447 static int unload_module(
void)
457 static int load_module(
void)
467 AST_MODULE_INFO_STANDARD_EXTENDED(
ASTERISK_GPL_KEY,
"SF 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.
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().
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
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define DSP_DIGITMODE_RELAXDTMF
static int read_sf_digits(struct ast_channel *chan, char *buf, int buflen, int timeout, int maxdigits, int freq, int features, int extrapulses)
Detects SF digits on channel using DSP.
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.
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_str_to_int(const char *str, int *res)
Convert the given string to a signed integer.
#define DSP_DIGITMODE_MUTEMAX
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
int ast_sf_stream(struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *chan2, const char *digits, int frequency, int is_external)
Send a string of SF digits to a channel.
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
int ast_dsp_set_freqmode(struct ast_dsp *dsp, int freq, int dur, int db, int squelch)
Set arbitrary frequency detection mode.
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.
#define DSP_FEATURE_FREQ_DETECT
#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.
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.
#define AST_APP_ARG(name)
Define an application argument.