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

SF 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 SF_BETWEEN   600
 
#define SF_MIN_DETECT   50
 
#define SF_MIN_OFF   25
 
#define SF_ON   67
 

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_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,"SF Sender and Receiver Applications")
 
static int load_module (void)
 
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. More...
 
static int read_sf_exec (struct ast_channel *chan, const char *data)
 
static int sendsf_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 }, [ 'm' ] = { .flag = OPT_MUTE }, [ 'q' ] = { .flag = OPT_QUELCH }, [ 'r' ] = { .flag = OPT_RELAXED }, }
 
static const char * readsf_name = "ReceiveSF"
 
static const char sendsf_name [] = "SendSF"
 

Detailed Description

SF sender and receiver applications.

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

Definition in file app_sf.c.

Function Documentation

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

Detects SF digits on channel using DSP.

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
maxdigitsMaximum number of digits
freqFrequency to use
featuresDSP features
extrapulsesWhether to recognize extra pulses
Return values
0if successful
-1if unsuccessful (including hangup).

Definition at line 183 of file app_sf.c.

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

183  {
184  /* Bell System Technical Journal 39 (Nov. 1960) */
185  #define SF_MIN_OFF 25
186  #define SF_ON 67
187  #define SF_BETWEEN 600
188  #define SF_MIN_DETECT 50
189 
190  struct ast_dsp *dsp = NULL;
191  struct ast_frame *frame = NULL;
192  struct timeval start, pulsetimer, digittimer;
193  int remaining_time = timeout;
194  char *str = buf;
195  int hits = 0, digits_read = 0;
196  unsigned short int sf_on = 0;
197  int res = 0;
198 
199  if (!(dsp = ast_dsp_new())) {
200  ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
201  pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "ERROR");
202  return -1;
203  }
205  /* tolerance is 46 to 76% make break at 8 to 12 pps */
206  ast_dsp_set_freqmode(dsp, freq, SF_MIN_DETECT, 16, 0);
207 
208  start = ast_tvnow();
209  *str = 0; /* start with empty output buffer */
210 
211  while (timeout == 0 || remaining_time > 0) {
212  if (timeout > 0) {
213  remaining_time = ast_remaining_ms(start, timeout);
214  if (remaining_time <= 0) {
215  pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "TIMEOUT");
216  break;
217  }
218  }
219  if (digits_read >= (buflen - 1)) { /* we don't have room to store any more digits (very unlikely to happen for a legitimate reason) */
220  /* This result will probably not be usable, so status should not be START */
221  pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "MAXDIGITS");
222  break;
223  }
224  if (ast_waitfor(chan, 1000) > 0) {
225  frame = ast_read(chan);
226  if (!frame) {
227  ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
228  pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "HANGUP");
229  break;
230  } else if (frame->frametype == AST_FRAME_VOICE) {
231  frame = ast_dsp_process(chan, dsp, frame);
232  if (frame->frametype == AST_FRAME_DTMF) {
233  char result = frame->subclass.integer;
234  if (result == 'q') {
235  sf_on = 1;
236  pulsetimer = ast_tvnow(); /* reset the pulse timer */
237  /* now, we need at least a 33ms pause to register the pulse */
238  }
239  } else {
240  if (sf_on) {
241  int timeleft = ast_remaining_ms(pulsetimer, SF_MIN_OFF);
242  if (timeleft <= 0) {
243  sf_on = 0;
244  /* The pulse needs to end no more than 30ms after we detected it */
245  if (timeleft > -30) {
246  hits++;
247  digittimer = ast_tvnow(); /* reset the digit timer */
248  ast_debug(5, "Detected SF pulse (pulse #%d)\n", hits);
249  ast_dsp_free(dsp);
250  if (!(dsp = ast_dsp_new())) {
251  ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
252  pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "ERROR");
253  ast_frfree(frame);
254  return -1;
255  }
257  ast_dsp_set_freqmode(dsp, freq, SF_MIN_DETECT, 16, 0);
258  } else {
259  ast_debug(5, "SF noise, ignoring, time elapsed was %d ms\n", timeleft);
260  }
261  }
262  } else if (hits > 0 && ast_remaining_ms(digittimer, SF_BETWEEN) <= 0) {
263  /* has the digit finished? */
264  ast_debug(2, "Received SF digit: %d\n", hits);
265  digits_read++;
266  if (hits > 10) {
267  if (extrapulses) {
268  /* dahdi-base.c translates 11 to * and 12 to # */
269  if (hits == 11) {
270  hits = '*';
271  } else if (hits == 12) {
272  hits = '#';
273  } else if (hits == 13) {
274  hits = 'D';
275  } else if (hits == 14) {
276  hits = 'C';
277  } else if (hits == 15) {
278  hits = 'B';
279  } else if (hits == 16) {
280  hits = 'A';
281  } else {
282  ast_debug(3, "Got %d SF pulses, is someone playing with the phone?\n", hits);
283  hits = 'A';
284  }
285  *str++ = hits;
286  } else {
287  ast_debug(2, "Got more than 10 pulses, truncating to 10\n");
288  hits = 0; /* 10 dial pulses = digit 0 */
289  *str++ = hits + '0';
290  }
291  } else {
292  if (hits == 10) {
293  hits = 0; /* 10 dial pulses = digit 0 */
294  }
295  *str++ = hits + '0';
296  }
297  *str = 0;
298  hits = 0;
299  if (maxdigits > 0 && digits_read >= maxdigits) {
300  pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "START");
301  ast_frfree(frame);
302  break;
303  }
304  }
305  }
306  }
307  ast_frfree(frame);
308  } else {
309  pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "HANGUP");
310  res = -1;
311  }
312  }
313  if (dsp) {
314  ast_dsp_free(dsp);
315  }
316  ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
317  return res;
318 }
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
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 ast_dsp_set_freqmode(struct ast_dsp *dsp, int freq, int dur, int db, int squelch)
Set arbitrary frequency detection mode.
Definition: dsp.c:1872
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
#define DSP_FEATURE_FREQ_DETECT
Definition: dsp.h:45