Managing an Internal Dialtone with asterisk

I run an asterisk PBX, largely to handle the complex telephony needs of Sacramento Medical Oasis, Inc. If you don’t know what an asterisk PBX is, you can stop reading now and you won’t miss anything. I promise.

I had a pretty simple task that I needed asterisk to perform: give a caller a special dial tone, wait for the caller to key a 10-digit number, stopping the dialtone at the first key press. It’s something that telephones do every day, and I didn’t expect it to be any trouble. I found that it wasn’t quite so easy.

The most logical thing to do was to play a dial tone using Playtones(dial), then WaitExten(). Alas, Playtones() cheerfully continues to play the dialtone throughout all ten key presses — that’s non-standard and rather disconcerting.

Of course, BackGround() will play a sound file and stop playing with a keypress, but you’d have to have a long sound file of a dial tone and make some provision for detecting when the file was finished and either play it again or go to some kind of time-out sequence. Looping the sound file will also cause audio glitches. A cursory search of the net didn’t turn up any usable dialtone files (my needs are rather specific, though easily handled through playtones). It also seemed like rather a kludge.

My search did turn up a surprising number of asterisk users posting to bulletin boards with the same issue I had. I had assumed that I just missed something pretty basic, but apparently not. The posts all had the same refrain (“this should be easy — am I missing something?”) and none had gotten satisfactory answers.

The most helpful answer referenced the DISA() application. It’s oh-so-close but, as is often the case with a built-in solution, it lacks the flexibility I need. I suspect that for most of the posters, however, it’s the best solution.

The answer for me turned out to be pretty simple after all. To wit:

.
.
.
; play our custom dialtone and wait for keypress
exten => s,n,playtones(custom_dialtone)
exten => s,n,waitExten(15)

; stop the dialtone when we get a keypress
; you could also define single-key escapes here [eg. exten => #,1,goto(main_loop,s,1)]
exten => _X,1,stopPlaytones
exten => _X,n,set(FIRSTDIGIT=${EXTEN})
exten => _X,n,goto(get_the_rest,s,1)

exten => t,1,hangup
exten => i,1,hangup

[get_the_rest]
exten => s,1,waitExten(15)

; for now we'll just read back the entered ten-digit number and hang up
exten => _XXXXXXXXX,1,sayDigits(${FIRSTDIGIT}${EXTEN})
exten => _XXXXXXXXX,n,hangup

exten => t,1,hangup
exten => i,1,hangup

Perhaps not trivial, but certainly not too complicated.

–Ron – 2010-12-28