Sangoma A500 Install / Setup problem

Hi,

I have been trying to install and setup a new A500 BRI card over the last few days and getting no where fast.

The card is a 3 port version plugged into 3 ISDN2e lines ( 6 channels ). I am based in the UK so using a Eurpoean setup.

I am also using the latest wanpipe version 3.3.2 as describing in the install WIKI.

I am pretty sure the problem is down to me not knowing how to install / set it up properly.

I am pretty sure the card is installed OK because when i make a call i get the example message saying the card is installed OK. I was getting the same message when i called into the system externally but now it just cuts me off.

Can anyone help, from what i have read it may be to do with my extensions.conf file. I have copied the file below. I have also left the line that plays the recorded message in, i have tried removing these lines but then nothing happens when diallying internally, trying to make an external call or trying to dial out.

Any help will be very much appreciated

Thanks…Pigsfoot

Extensions.conf…
; do not edit this file, this is an auto-generated file by freepbx
; all modifications must be done from the web gui

; FreePBX
; Copyright © 2004 Coalescent Systems Inc (Canada)
; Copyright © 2006 Why Pay More 4 Less Pty Ltd (Australia)
; Copyright © 2007 Astrogen LLC (USA)
; Released under the GNU GPL Licence version 2.

; dialparties.agi (http://www.sprackett.com/asterisk/)
; Asterisk::AGI (http://asterisk.gnuinter.net/)
; gsm (http://www.ibiblio.org/pub/Linux/utils/compress/!INDEX.short.html)
; loligo sounds (http://www.loligo.com/asterisk/sounds/)
; mpg123 (http://voip-info.org/wiki-Asterisk+config+musiconhold.conf)

;************************** -WARNING- ****************************************
; *
; This include file is to be used with extreme caution. In almost all cases *
; any custom dialplan SHOULD be put in extensions_custom.conf which will *
; not hurt freepbx generated dialplan. In some very rare and custom situation *
; users have a need to override what freepbx generates. Anything in this file *
; will do such. *
; *
#include extensions_override_freepbx.conf
; *
;************************** -WARNING- ****************************************

; include extension contexts generated from AMP
#include extensions_additional.conf

; Customizations to this dialplan should be made in extensions_custom.conf
; See extensions_custom.conf.sample for an example
#include extensions_custom.conf

[from-trunk] ; just an alias since VoIP shouldn’t be called PSTN
include => from-pstn

[from-pstn]
include => from-pstn-custom ; create this context in extensions_custom.conf to include customizations
include => ext-did
include => from-did-direct ; MODIFICATOIN (PL) for findmefollow if enabled, should be bofore ext-local
include => ext-did-catchall ; THIS MUST COME AFTER ext-did
exten => fax,1,Goto(ext-fax,in_fax,1)

; MODIFICATION (PL)
;
; Required to assure that direct dids go to personal ring group before local extension.
; This could be auto-generated however I it is prefered to be put here and hard coded
; so that it can be modified if ext-local should take precedence in certain situations.
; will have to decide what to do later.
;
[from-did-direct]
include => ext-findmefollow
include => ext-local

; ############################################################################
; Macros [macro]
; ############################################################################

; Rings one or more extensions. Handles things like call forwarding and DND
; We don’t call dial directly for anything internal anymore.
; ARGS: $TIMER, $OPTIONS, $EXT1, $EXT2, $EXT3, …
; Use a Macro call such as the following:
; Macro(dial,$DIAL_TIMER,$DIAL_OPTIONS,$EXT1,$EXT2,$EXT3,…)
[macro-dial]
exten => s,1,GotoIf($["${MOHCLASS}" = “”]?dial)
exten => s,n,SetMusicOnHold(${MOHCLASS})
exten => s,n(dial),AGI(dialparties.agi)
exten => s,n,NoOp(Returned from dialparties with no extensions to call and DIALSTATUS: ${DIALSTATUS})

exten => s,n+2(normdial),Dial(${ds}) ; dialparties will set the priority to 10 if $ds is not null
exten => s,n,Set(DIALSTATUS=${IF($["${DIALSTATUS_CW}"!="" ]?${DIALSTATUS_CW}:${DIALSTATUS})})

exten => s,20(huntdial),NoOp(Returned from dialparties with hunt groups to dial )
exten => s,n,Set(HuntLoop=0)
exten => s,n(a22),GotoIf($[${HuntMembers} >= 1]?a30) ; if this is from rg-group, don’t strip prefix
exten => s,n,NoOp(Returning there are no members left in the hunt group to ring)

; dialparties.agi has setup the dialstring for each hunt member in a variable labeled HuntMember0, HuntMember1 etc for each iteration
; and The total number in HuntMembers. So for each iteration, we will update the CALLTRACE Data.
;
exten => s,n+2(a30),Set(HuntMember=HuntMember${HuntLoop})
exten => s,n,GotoIf($[$["${CALLTRACE_HUNT}" != “” ] & $["${RingGroupMethod}" = “hunt” ]]?a32:a35)
exten => s,n(a32),Set(CT_EXTEN=${CUT(FILTERED_DIAL,$[${HuntLoop} + 1])})
exten => s,n,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT})
exten => s,n,Goto(s,a42)

;Set Call Trace for each hunt member we are going to call “Memory groups have multiple members to set CALL TRACE For hence the loop
;
exten => s,n(a35),GotoIf($[$[”${CALLTRACE_HUNT}" != “” ] & $["${RingGroupMethod}" = “memoryhunt” ]]?a36:a50)
exten => s,n(a36),Set(CTLoop=0)
exten => s,n(a37),GotoIf($[${CTLoop} > ${HuntLoop}]?a42) ; if this is from rg-group, don’t strip prefix
exten => s,n,Set(CT_EXTEN=${CUT(FILTERED_DIAL,$[${CTLoop} + 1])})
exten => s,n,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT})
exten => s,n,Set(CTLoop=$[1 + ${CTLoop}])
exten => s,n,Goto(s,a37)

exten => s,n(a42),Dial(${${HuntMember}}${ds})
exten => s,n,Set(HuntLoop=$[1 + ${HuntLoop}])
exten => s,n,GotoIf($[$[$[“foo${RingGroupMethod}” != “foofirstavailable”] & $[“foo${RingGroupMethod}” != “foofirstnotonphone”]] | $[“foo${DialStatus}” = “fooBUSY”]]?a46)
exten => s,n,Set(HuntMembers=0)
exten => s,n(a46),Set(HuntMembers=$[${HuntMembers} - 1])
exten => s,n,Goto(s,a22)

exten => s,n(a50),DBdel(CALLTRACE/${CT_EXTEN})
exten => s,n,Goto(s,a42)

; make sure hungup calls go here so that proper cleanup occurs from call confirmed calls and the like
;
exten => h,1,Macro(hangupcall)

; Ring an extension, if the extension is busy or there is no answer send it
; to voicemail
; ARGS: $VMBOX, $EXT
[macro-exten-vm]
exten => s,1,Macro(user-callerid)

exten => s,n,Set(FROMCONTEXT=exten-vm)
exten => s,n,Set(VMBOX=${ARG1})
exten => s,n,Set(EXTTOCALL=${ARG2})
exten => s,n,Set(CFUEXT=${DB(CFU/${EXTTOCALL})})
exten => s,n,Set(CFBEXT=${DB(CFB/${EXTTOCALL})})
exten => s,n,Set(RT=${IF($[$["${VMBOX}"!=“novm”] | $[“foo${CFUEXT}”!=“foo”]]?${RINGTIMER}:"")})
exten => s,n,Macro(record-enable,${EXTTOCALL},IN)

exten => s,n,Macro(dial,${RT},${DIAL_OPTIONS},${EXTTOCALL})
exten => s,n,Set(SV_DIALSTATUS=${DIALSTATUS})
exten => s,n,GosubIf($[$["${SV_DIALSTATUS}"=“NOANSWER”] & $[“foo${CFUEXT}”!=“foo”]]?docfu,1) ; check for CFU in use on no answer
exten => s,n,GosubIf($[$["${SV_DIALSTATUS}"=“BUSY”] & $[“foo${CFBEXT}”!=“foo”]]?docfb,1) ; check for CFB in use on busy
exten => s,n,Set(DIALSTATUS=${SV_DIALSTATUS})
exten => s,n,NoOp(Voicemail is ‘${VMBOX}’)
exten => s,n,GotoIf($["${VMBOX}" = “novm”]?s-${DIALSTATUS},1) ; no voicemail in use for this extension
exten => s,n,NoOp(Sending to Voicemail box ${EXTTOCALL})
exten => s,n,Macro(vm,${VMBOX},${DIALSTATUS})

; Try the Call Forward on No Answer / Unavailable number
exten => docfu,1,Set(RTCFU=${IF($["${VMBOX}"!=“novm”]?${RINGTIMER}:"")})
exten => docfu,n,Dial(Local/${CFUEXT}@from-internal/n,${RTCFU},${DIAL_OPTIONS})
exten => docfu,n,Return

; Try the Call Forward on Busy number
exten => docfb,1,Set(RTCFB=${IF($["${VMBOX}"!=“novm”]?${RINGTIMER}:"")})
exten => docfb,n,Dial(Local/${CFBEXT}@from-internal/n,${RTCFB},${DIAL_OPTIONS})
exten => docfb,n,Return

; Extensions with no Voicemail box reporting BUSY come here
exten => s-BUSY,1,NoOp(Extension is reporting BUSY and not passing to Voicemail)
exten => s-BUSY,n,Playtones(busy)
exten => s-BUSY,n,Busy(20)

; Anything but BUSY comes here
exten => _s-.,1,Playtones(congestion)
exten => _s-.,n,Congestion(10)

;------------------------------------------------------------------------
; [macro-vm]
;------------------------------------------------------------------------
; CONTEXT: macro-vm
; PURPOSE: call voicemail system and extend with personal ivr
;
; Under normal use, this macro will call the voicemail system with the extension and
; desired greeting mode of busy, unavailable or as specified with direct voicemail
; calls (usually unavailable) when entered from destinations.
;
; The voicemail system’s two greetings have been ‘hijacked’ as follows to extend the
; system by giving the option of a private ‘ivr’ for each voicemail user. The following
; applies to both the busy and unavailable modes of voicemail and can be applied to one
; or both, and differently.
;
; Global Defaults:
;
; The following are default values, used in both busy and unavail modes if no specific
; values are specified.
;
; VMX_REPEAT
; The number of times to repeat the users message if no option is pressed.
; VMX_TIMEOUT
; The timeout to wait after playing message before repeating or giving up.
; VMX_LOOPS
; The number of times it should replay the message and check for an option when
; an invalid option is pressed.
;
; VMX_OPTS_DOVM
; Default voicemail option to use if vm is chosen as an option. No options will
; cause Allison’s generic message, ‘s’ will go straight to beep.
; VMX_OPTS_TIMEOUT
; Default voicemail option to use if it times out with no options. No options will
; cause Allison’s generic message, ‘s’ will go straight to beep.
; IF THE USER PRESSES # - it will look like a timeout as well since no option will
; be presented. If the user wishes to enable a mode where a caller can press #
; during their message and it goes straight to voicemail with only a ‘beep’ then
; this should be set to ‘s’.
; VMX_OPTS_LOOPS
; Default voicemail option to use if to many wrong options occur. No options will
; cause Allison’s generic message, ‘s’ will go straight to beep.
;
; VMX_CONTEXT
; Default context for user destinations if not supplied in the user’s settings
; VMX_PRI
; Default priority for user destinations if not supplied in the user’s settings
;
; VMX_TIMEDEST_CONTEXT
; Default context for timeout destination if not supplied in the user’s settings
; VMX_TIMEDEST_EXT
; Default extension for timeout destination if not supplied in the user’s settings
; VMX_TIMEDEST_PRI
; Default priority for timeout destination if not supplied in the user’s settings
;
; VMX_LOOPDEST_CONTEXT
; Default context for loops destination if not supplied in the user’s settings
; VMX_LOOPDEST_EXT
; Default extension for loops destination if not supplied in the user’s settings
; VMX_LOOPDEST_PRI
; Default priority for loops destination if not supplied in the user’s settings
;
;
; The AMPUSER database variable has been extended with a ‘vmx’ tree (vm-extension). A
; duplicate set is included for both unavail and busy. You could choose for to have an
; ivr when unavail is taken, but not with busy - or a different once with busy.
; The full list is below, each specific entry is futher described:
;
; state: Whether teh current mode is enabled or disabled. Anything but ‘enabled’ is
; treated as disabled.
; repeat: This is the number of times that the users message should be played after the
; timeout if the user has not entered anything. It is just a variable to the
; Read() function which will do the repeating.
; timeout: This is how long to wait after the message has been read for a response from
; the user. A caller can enter a digit any time during the playback.
; loops: This is the number of loops that the system will allow a caller to retry if
; they enter a bad menu choice, before going to the loop failover destination
; vmxopts: This is the vm options to send to the voicemail command used when a specific
; voicemail destination is chosen (inidcated by ‘dovm’ in the ext field). This is
; typically either set to ‘s’ or left blank. When set to ‘s’ there will be no
; message played when entering the voicemail, just a beep. When blank, you will
; have Allison’s generic message played. It is not typical to play the greetings
; since they have been ‘hijacked’ for these IVR’s and from a caller’s perspecitive
; this system appears interconnected with the voicemail so instructions can be
; left there.
; timedest: The three variables: ext, context and pri are the goto destination if the caller
; enters no options and it timesout. None have to be set and a system default
; will be used. If just ext is set, then defaults will be used for context and
; pri, etc.
; loopdest: This is identical to timedest but used if the caller exceeds the maximum invalid
; menu choices.
; [0-9*]: The user can specify up to 11 ivr options, all as single digits from 0-9 or . The
; # key can not be used since it is used as a terminator key for the Read command
; and will never be returned. A minimum of the ext must be specified for each valid
; option and as above, the context and priority can also be specified if the default
; is not to be used.
; Option ‘0’ takes on a special meaning. Since a user is able to break out of the
; voicemail command once entering it with a 0, if specified, the 0 destination will
; be used.
; Option '
’ can also be used to breakout. It is undecided at this point whether
; providing that option will be used as well. (probably should).
;
;
; /AMPUSER//vmx/[busy|unavail]/state: enabled|disabled
; /AMPUSER//vmx/[busy|unavail]/repeat: n (times to repeat message)
; /AMPUSER//vmx/[busy|unavail]/timeout: n (timeout to wait for digit)
; /AMPUSER//vmx/[busy|unavail]/loops: n (loop returies for invalid entries)
; /AMPUSER//vmx/[busy|unavail]/vmxopts/dovm: vmoptions (if ext is dovm)
; /AMPUSER//vmx/[busy|unavail]/vmxopts/timeout: vmoptions (if timeout)
; /AMPUSER//vmx/[busy|unavail]/vmxopts/loops: vmoptions (if loops)
; /AMPUSER//vmx/[busy|unavail]/timedest/ext: extension (if timeout)
; /AMPUSER//vmx/[busy|unavail]/timedest/context: context (if timeout)
; /AMPUSER//vmx/[busy|unavail]/timedest/pri: priority (if timeout)
; /AMPUSER//vmx/[busy|unavail]/loopdest/ext: extension (if too many failures)
; /AMPUSER//vmx/[busy|unavail]/loopdest/context: context (if too many failures)
; /AMPUSER//vmx/[busy|unavail]/loopdest/pri: priority (if too many failures)
; /AMPUSER//vmx/[busy|unavail]/[0-9*]/ext: extension (dovm for vm access)
; /AMPUSER//vmx/[busy|unavail]/[0-9*]/context: context
; /AMPUSER//vmx/[busy|unavail]/[0-9*]/pri: priority
;------------------------------------------------------------------------
[macro-vm]
; ARG1 - extension
; ARG2 - DIRECTDIAL/BUSY
; ARG3 - RETURN makes macro return, otherwise hangup
exten => s,1,Macro(user-callerid,SKIPTTL)
exten => s,n,Set(VMGAIN=${IF($[“foo${VM_GAIN}”!=“foo”]?“g(${VM_GAIN})”:"")})
;
; If BLKVM_OVERRIDE is set, then someone told us to block calls from going to
; voicemail. This variable is reset by the answering channel so subsequent
; transfers will properly function.
;
exten => s,n,GotoIf($[“foo${DB(${BLKVM_OVERRIDE})}” != “fooTRUE”]?vmx,1)
;
; we didn’t branch so block this from voicemail
;
exten => s,n,Noop(CAME FROM: ${NODEST} - Blocking VM cause of key: ${DB(BLKVM_OVERRIDE)})

; If vmx not enabled for the current mode,then jump to normal voicemail behavior
; also - if not message (no-msg) is requested, straight to voicemail
;
exten => vmx,1,GotoIf($["${ARG2}"=“NOMESSAGE”]?s-${ARG2},1)
exten => vmx,n,Set(MODE=${IF($["${ARG2}"=“BUSY”]?busy:unavail)})
exten => vmx,n,GotoIf($["${ARG2}" != “DIRECTDIAL”]?notdirect)
exten => vmx,n,Set(MODE=${IF($["${REGEX("[b]" ${VM_DDTYPE})}" = “1”]?busy:${MODE})})
exten => vmx,n(notdirect),Noop(Checking if ext ${ARG1} is enabled: ${DB(AMPUSER/${ARG1}/vmx/${MODE}/state)})
exten => vmx,n,GotoIf($["${DB(AMPUSER/${ARG1}/vmx/${MODE}/state)}" != “enabled”]?s-${ARG2},1)

; If the required voicemail file does not exist, then abort and go to normal voicemail behavior
;
; TODO: there have been errors using System() with jump to 101 where asterisk works fine at the begining and
; then starts to jump to 101 even on success. This new mode is being tried with the SYSTEM Status which
; returns SUCCESS when the command returned succcessfully with a 0 app return code.
;
exten => vmx,n,Macro(get-vmcontext,${ARG1})
;exten => vmx,n,TrySystem(/bin/ls ${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE}.[wW][aA][vV])
exten => vmx,n,AGI(checksound.agi,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE})
exten => vmx,n,GotoIf($["${SYSTEMSTATUS}" != “SUCCESS”]?nofile)

; Get the repeat, timeout and loop times to use if they are overriden form the global settings
;
exten => vmx,n,Set(LOOPCOUNT=0)
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/repeat)}" = “0”]?vmxtime)
exten => vmx,n,Set(VMX_REPEAT=${DB_RESULT})
exten => vmx,n(vmxtime),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timeout)}" = “0”]?vmxloops)
exten => vmx,n,Set(VMX_TIMEOUT=${DB_RESULT})
exten => vmx,n(vmxloops),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loops)}" = “0”]?vmxanswer)
exten => vmx,n,Set(VMX_LOOPS=${DB_RESULT})
exten => vmx,n(vmxanswer),Answer()

; Now play the users voicemail recording as the basis for their ivr, the Read command will repeat as needed and if it timesout
; then we go to the timeout. Otherwise handle invalid options by looping until the limit until a valid option is played.
;
exten => vmx,n(loopstart),Read(ACTION,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE},1,skip,${VMX_REPEAT},${VMX_TIMEOUT})
exten => vmx,n,GotoIf($["${EXISTS(${ACTION})}" = “1”]?checkopt)

; If we are here we timed out, go to the required destination
;
exten => vmx,n(noopt),Noop(Timeout: going to timeout dest)
exten => vmx,n,Set(VMX_OPTS=${VMX_OPTS_TIMEOUT})
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/timeout)}" = “0”]?chktime)
exten => vmx,n,Set(VMX_OPTS=${DB_RESULT})
exten => vmx,n(chktime),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/ext)}" = “0”]?dotime)
exten => vmx,n,Set(VMX_TIMEDEST_EXT=${DB_RESULT})
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/context)}" = “0”]?timepri)
exten => vmx,n,Set(VMX_TIMEDEST_CONTEXT=${DB_RESULT})
exten => vmx,n(timepri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/pri)}" = “0”]?dotime)
exten => vmx,n,Set(VMX_TIMEDEST_PRI=${DB_RESULT})
exten => vmx,n(dotime),Goto(${VMX_TIMEDEST_CONTEXT},${VMX_TIMEDEST_EXT},${VMX_TIMEDEST_PRI})

; We got an option, check if the option is defined, or one of the system defaults
;
exten => vmx,n(checkopt),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/ext)}" = “1”]?doopt)
exten => vmx,n,GotoIf($["${ACTION}" = “0”]?o,1)
exten => vmx,n,GotoIf($["${ACTION}" = “*”]?adef,1)

; Got invalid option loop until the max
;
exten => vmx,n,Set(LOOPCOUNT=$[${LOOPCOUNT} + 1])
exten => vmx,n,GotoIf($[${LOOPCOUNT} > ${VMX_LOOPS}]?toomany)
exten => vmx,n,Playback(pm-invalid-option&please-try-again)
exten => vmx,n,Goto(loopstart)

; tomany: to many invalid options, go to the specified destination
;
exten => vmx,n(toomany),Noop(Too Many invalid entries, got to invalid dest)
exten => vmx,n,Set(VMX_OPTS=${VMX_OPTS_LOOPS})
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/loops)}" = “0”]?chkloop)
exten => vmx,n,Set(VMX_OPTS=${DB_RESULT})
exten => vmx,n(chkloop),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/ext)}" = “0”]?doloop)
exten => vmx,n,Set(VMX_LOOPDEST_EXT=${DB_RESULT})
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/context)}" = “0”]?looppri)
exten => vmx,n,Set(VMX_LOOPDEST_CONTEXT=${DB_RESULT}) ;TODO make configurable per above
exten => vmx,n(looppri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/pri)}" = “0”]?doloop)
exten => vmx,n,Set(VMX_LOOPDEST_PRI=${DB_RESULT}) ;TODO make configurable per above
exten => vmx,n(doloop),Goto(${VMX_LOOPDEST_CONTEXT},${VMX_LOOPDEST_EXT},${VMX_LOOPDEST_PRI})

; doopt: execute the valid option that was chosen
;
exten => vmx,n(doopt),Noop(Got a valid option: ${DB_RESULT})
exten => vmx,n,Set(VMX_EXT=${DB_RESULT})
;
; Special case, if this option was to go to voicemail, set options and go
;
exten => vmx,n,GotoIf($["${VMX_EXT}" != “dovm”]?getdest)
exten => vmx,n(vmxopts),Set(VMX_OPTS=${VMX_OPTS_DOVM})
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/dovm)}" = “0”]?vmxdovm)
exten => vmx,n(vmxopts),Set(VMX_OPTS=${DB_RESULT})
exten => vmx,n(vmxdovm),goto(dovm,1)
;
; General case, setup the goto destination and go there (no error checking, its up to the GUI’s to assure
; reasonable values
;
exten => vmx,n(getdest),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/context)}" = “0”]?vmxpri)
exten => vmx,n,Set(VMX_CONTEXT=${DB_RESULT})
exten => vmx,n(vmxpri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/pri)}" = “0”]?vmxgoto)
exten => vmx,n,Set(VMX_PRI=${DB_RESULT})
exten => vmx,n(vmxgoto),Goto(${VMX_CONTEXT},${VMX_EXT},${VMX_PRI})

; If the required voicemail file is not present, then revert to normal voicemail
; behavior treating as if it was not set
;
exten => vmx,n(nofile),Noop(File for mode: ${MODE} does not exist, SYSTEMSTATUS: ${SYSTEMSTATUS}, going to normal voicemail)
exten => vmx,n,Goto(s-${ARG2},1)

; Drop into voicemail either as a direct destination (in which case VMX_OPTS might be set to something) or
; if the user timed out or broke out of the loop then VMX_OPTS is always cleared such that an Allison
; message is played and the caller know’s what is going on.
;
exten => dovm,1,Noop(VMX Timeout - go to voicemail)
exten => dovm,n,Voicemail(${ARG1}@${VMCONTEXT},${VMX_OPTS}${VMGAIN}) ; no flags, so allison plays please leave …
exten => dovm,n,Goto(exit-${VMSTATUS},1)

exten => s-BUSY,1,NoOp(BUSY voicemail)
exten => s-BUSY,n,Macro(get-vmcontext,${ARG1})
exten => s-BUSY,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}b${VMGAIN}) ; Voicemail Busy message
exten => s-BUSY,n,Goto(exit-${VMSTATUS},1)

exten => s-NOMESSAGE,1,NoOp(NOMESSAGE (beeb only) voicemail)
exten => s-NOMESSAGE,n,Macro(get-vmcontext,${ARG1})
exten => s-NOMESSAGE,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}${VMGAIN}) ; Voicemail Busy message
exten => s-NOMESSAGE,n,Goto(exit-${VMSTATUS},1)

exten => s-DIRECTDIAL,1,NoOp(DIRECTDIAL voicemail)
exten => s-DIRECTDIAL,n,Macro(get-vmcontext,${ARG1})
exten => s-DIRECTDIAL,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}${VM_DDTYPE}${VMGAIN})
exten => s-DIRECTDIAL,n,Goto(exit-${VMSTATUS},1)

exten => _s-.,1,Macro(get-vmcontext,${ARG1})
exten => _s-.,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}u${VMGAIN}) ; Voicemail Unavailable message
exten => _s-.,n,Goto(exit-${VMSTATUS},1)

; If the user has a 0 option defined, use that for operator zero-out from within voicemail
; as well to keep it consistant with the menu structure
;
exten => o,1,Background(one-moment-please) ; 0 during vm message will hangup
exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/ext)}" = “0”]?doopdef)

exten => o,n,Set(VMX_OPDEST_EXT=${DB_RESULT})
exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/context)}" = “1”]?opcontext)
exten => o,n,Set(DB_RESULT=${VMX_CONTEXT})
exten => o,n(opcontext),Set(VMX_OPDEST_CONTEXT=${DB_RESULT})
exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/pri)}" = “1”]?oppri)
exten => o,n,Set(DB_RESULT=${VMX_PRI})
exten => o,n(oppri),Set(VMX_OPDEST_PRI=${DB_RESULT})

exten => o,n,Goto(${VMX_OPDEST_CONTEXT},${VMX_OPDEST_EXT},${VMX_OPDEST_PRI})
exten => o,n(doopdef),GotoIf($[“x${OPERATOR_XTN}”=“x”]?nooper:from-internal,${OPERATOR_XTN},1)
exten => o,n(nooper),GotoIf($[“x${FROM_DID}”=“x”]?nodid)
exten => o,n,Dial(Local/${FROM_DID)@from-pstn)
exten => o,n,Macro(hangup)
exten => o,n(nodid),Dial(Local/s@from-pstn)
exten => o,n,Macro(hangup)

; If the user has a * option defined, use that for the * out from within voicemail
; as well to keep it consistant with the menu structure
;
exten => a,1,Macro(get-vmcontext,${ARG1})
exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/ext)}" = “0”]?adef,1)

exten => a,n,Set(VMX_ADEST_EXT=${DB_RESULT})
exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}//context)}" = “1”]?acontext)
exten => a,n,Set(DB_RESULT=${VMX_CONTEXT})
exten => a,n(acontext),Set(VMX_ADEST_CONTEXT=${DB_RESULT})
exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/
/pri)}" = “1”]?apri)
exten => a,n,Set(DB_RESULT=${VMX_PRI})
exten => a,n(apri),Set(VMX_ADEST_PRI=${DB_RESULT})
exten => a,n,Goto(${VMX_ADEST_CONTEXT},${VMX_ADEST_EXT},${VMX_ADEST_PRI})

exten => adef,1,VoiceMailMain(${ARG1}@${VMCONTEXT})
exten => adef,n,Hangup

exten => exit-FAILED,1,Playback(im-sorry&an-error-has-occured)
exten => exit-FAILED,n,GotoIf($["${ARG3}" = “RETURN”]?exit-RETURN,1)
exten => exit-FAILED,n,Hangup()

exten => exit-SUCCESS,1,GotoIf($["${ARG3}" = “RETURN”]?exit-RETURN,1)
exten => exit-SUCCESS,n,Playback(goodbye)
exten => exit-SUCCESS,n,Hangup()

exten => exit-USEREXIT,1,GotoIf($["${ARG3}" = “RETURN”]?exit-RETURN,1)
exten => exit-USEREXIT,n,Playback(goodbye)
exten => exit-USEREXIT,n,Hangup()

exten => exit-RETURN,1,Noop(Returning From Voicemail because macro)

exten => t,1,Hangup()
;------------------------------------------------------------------------

;------------------------------------------------------------------------
; [macro-simple-dial]
;------------------------------------------------------------------------
; This macro was derived from macro-exten-vm, which is what is normally used to
; ring an extension. It has been simplified and designed to never go to voicemail
; and always return regardless of the DIALSTATUS for any incomplete call.
;
; It’s current primary purpose is to allow findmefollow ring an extension prior
; to trying the follow-me ringgroup that is provided.
;
; Ring an extension, if the extension is busy or there is no answer, return
; ARGS: $EXTENSION, $RINGTIME
;------------------------------------------------------------------------
[macro-simple-dial]
exten => s,1,Macro(user-callerid,SKIPTTL) ; already called from follow-me

; FROMCONTEXT was in the original macro-exten-vm where this macro was derived from. A
; search through all the modules does not come up with any place using this
; variable, but it is left here as a reminder in case there is functionality
; that eventually behaves in a certain way as a result of this variable being set
; and this macro has to masquerade as exten-vm.
;
exten => s,n,Set(EXTTOCALL=${ARG1})
exten => s,n,Set(RT=${ARG2})
exten => s,n,Set(CFUEXT=${DB(CFU/${EXTTOCALL})})
exten => s,n,Set(CFBEXT=${DB(CFB/${EXTTOCALL})})
exten => s,n,Macro(record-enable,${EXTTOCALL},IN)

exten => s,n,Macro(dial,${RT},${DIAL_OPTIONS},${EXTTOCALL})

exten => s,n,Set(PR_DIALSTATUS=${DIALSTATUS})

; if we return, thus no answer, and they have a CFU setting, then we try that next
;
exten => s,n,GosubIf($[$["${PR_DIALSTATUS}"=“NOANSWER”] & $[“foo${CFUEXT}”!=“foo”]]?docfu,1) ; check for CFU in use on no answer
exten => s,n,GosubIf($[$["${PR_DIALSTATUS}"=“BUSY”] & $[“foo${CFBEXT}”!=“foo”]]?docfb,1) ; check for CFB in use on busy
exten => s,n,Set(DIALSTATUS=${PR_DIALSTATUS})

; Nothing yet, then go to the end (which will just return, but in case we decide to do something with certain
; return situations, this is left in.
;
exten => s,n,Goto(s-${DIALSTATUS},1)

; Try the Call Forward on No Answer / Unavailable number.
; We want to try CFU if set, but we want the same ring timer as was set to our call (or do we want the
; system ringtimer? - probably not). Then if no answer there (assuming it doesn’t drop into their vm or
; something we return, which will have the net effect of returning to the followme setup.)
;
; want to avoid going to other follow-me settings here. So check if the CFUEXT is a user and if it is
; then direct it straight to ext-local (to avoid getting intercepted by findmefollow) otherwise send it
; to from-internal since it may be an outside line.
;
exten => docfu,1,GotoIf( $[ “foo${DB(AMPUSER/${CFUEXT}/device)}” = “foo” ]?chlocal)
exten => docfu,n,Dial(Local/${CFUEXT}@ext-local,${RT},${DIAL_OPTIONS})
exten => docfu,n,Return
exten => docfu,n(chlocal),Dial(Local/${CFUEXT}@from-internal/n,${RT},${DIAL_OPTIONS})
exten => docfu,n,Return

; Try the Call Forward on Busy number
exten => docfb,1,GotoIf( $[ “foo${DB(AMPUSER/${CFBEXT}/device)}” = “foo” ]?chlocal)
exten => docfb,n,Dial(Local/${CFBEXT}@ext-local,${RT},${DIAL_OPTIONS})
exten => docfb,n,Return
exten => docfb,n(chlocal),Dial(Local/${CFBEXT}@from-internal/n,${RT},${DIAL_OPTIONS})
exten => docfb,n,Return

; In all cases of no connection, come here and simply return, since the calling dialplan will
; decide what to do next
exten => _s-.,1,NoOp(Extension is reporting ${EXTEN})
;------------------------------------------------------------------------

; get the voicemail context for the user in ARG1
[macro-get-vmcontext]
exten => s,1,Set(VMCONTEXT=${DB(AMPUSER/${ARG1}/voicemail)})
exten => s,2,GotoIf($[“foo${VMCONTEXT}” = “foo”]?200:300)
exten => s,200,Set(VMCONTEXT=default)
exten => s,300,NoOp()

; For some reason, if I don’t run setCIDname, CALLERID(name) will be blank in my AGI
; ARGS: none
[macro-fixcid]
exten => s,1,Set(CALLERID(name)=${CALLERID(name)})

; Ring groups of phones
; ARGS: comma separated extension list
; 1 - Ring Group Strategy
; 2 - ringtimer
; 3 - prefix
; 4 - extension list
[macro-rg-group]
exten => s,1,Macro(user-callerid,SKIPTTL) ; already called from ringgroup
exten => s,2,GotoIf($["${CALLERID(name):0:${LEN(${RGPREFIX})}}" != “${RGPREFIX}”]?4:3) ; check for old prefix
exten => s,3,Set(CALLERID(name)=${CALLERID(name):${LEN(${RGPREFIX})}}) ; strip off old prefix
exten => s,4,Set(RGPREFIX=${ARG3}) ; set new prefix
exten => s,5,Set(CALLERID(name)=${RGPREFIX}${CALLERID(name)}) ; add prefix to callerid name
exten => s,6,Set(RecordMethod=Group) ; set new prefix
exten => s,7,Macro(record-enable,${MACRO_EXTEN},${RecordMethod})
exten => s,8,Set(RingGroupMethod=${ARG1}) ;
exten => s,9,Macro(dial,${ARG2},${DIAL_OPTIONS},${ARG4})
exten => s,10,Set(RingGroupMethod=’’) ;

;
; Outgoing channel(s) are busy … inform the client
; but use noanswer features like ringgroups don’t break by being answered
; just to play the message.
;
[macro-outisbusy]
exten => s,1,Playback(all-circuits-busy-now,noanswer)
exten => s,n,Playback(pls-try-call-later,noanswer)
exten => s,n,Macro(hangupcall)

; What to do on hangup.
[macro-hangupcall]
exten => s,1,ResetCDR(w)
exten => s,n,NoCDR()

; Cleanup any remaining RG flag
;
exten => s,n,GotoIf($[ “x${USE_CONFIRMATION}” = “x” | “x${RINGGROUP_INDEX}” = “x” | “${CHANNEL}” != “${UNIQCHAN}”]?skiprg)
exten => s,n,Noop(Cleaning Up Confirmation Flag: RG/${RINGGROUP_INDEX}/${CHANNEL})
exten => s,n,DBDel(RG/${RINGGROUP_INDEX}/${CHANNEL})

; Cleanup any remaining BLKVM flag
;
exten => s,n(skiprg),GotoIf($[ “x${BLKVM_BASE}” = “x” | “BLKVM/${BLKVM_BASE}/${CHANNEL}” != “${BLKVM_OVERRIDE}” ]?skipblkvm)
exten => s,n,Noop(Cleaning Up Block VM Flag: ${BLKVM_OVERRIDE})
exten => s,n,DBDel(${BLKVM_OVERRIDE})

; Cleanup any remaining FollowMe DND flags
;
exten => s,n(skipblkvm),GotoIf($[ “x${FMGRP}” = “x” | “x${FMUNIQUE}” = “x” | “${CHANNEL}” != “${FMUNIQUE}” ]?theend)
exten => s,n,DBDel(FM/DND/${FMGRP}/${CHANNEL})

exten => s,n(theend),Hangup

[macro-faxreceive]
exten => s,1,Set(FAXFILE=${ASTSPOOLDIR}/fax/${UNIQUEID}.tif)
exten => s,2,Set(EMAILADDR=${FAX_RX_EMAIL})
exten => s,3,rxfax(${FAXFILE})
exten => s,103,Set(EMAILADDR=${FAX_RX_EMAIL})
exten => s,104,Goto(3)

; dialout and strip the prefix
[macro-dialout]
exten => s,1,Macro(user-callerid,SKIPTTL)
exten => s,2,GotoIf($["${ECID${CALLERID(number)}}" = “”]?5) ;check for CID override for exten
exten => s,3,Set(CALLERID(all)=${ECID${CALLERID(number)}})
exten => s,4,Goto(7)
exten => s,5,GotoIf($["${OUTCID_${ARG1}}" = “”]?7) ;check for CID override for trunk
exten => s,6,Set(CALLERID(all)=${OUTCID_${ARG1}})
exten => s,7,Set(length=${LEN(${DIAL_OUT_${ARG1}})})
exten => s,8,Dial(${OUT_${ARG1}}/${ARG2:${length}})
exten => s,9,Playtones(congestion)
exten => s,10,Congestion(5)
exten => s,109,Macro(outisbusy)

; dialout using default OUT trunk - no prefix
[macro-dialout-default]
exten => s,1,Macro(user-callerid,SKIPTTL)
exten => s,2,Macro(record-enable,${CALLERID(number)},OUT)
exten => s,3,Macro(outbound-callerid,${ARG1})
exten => s,4,Dial(${OUT}/${ARG1})
exten => s,5,Playtones(congestion)
exten => s,6,Congestion(5)
exten => s,105,Macro(outisbusy)

[macro-dialout-trunk-predial-hook]
; this macro intentially left blank so it may be safely overwritten for any custom
; requirements that an installatin may have.
;
; MACRO RETURN CODE: ${PREDIAL_HOOK_RET}
; if set to “BYPASS” then this trunk will be skipped
;

[macro-record-enable]
exten => s,1,GotoIf($[${LEN(${BLINDTRANSFER})} > 0]?2:4)
exten => s,2,ResetCDR(w)
exten => s,3,StopMonitor()
exten => s,4,AGI(recordingcheck,${STRFTIME(${EPOCH},%Y%m%d-%H%M%S)},${UNIQUEID})
exten => s,5,Noop(No recording needed)
exten => s,999,MixMonitor(${CALLFILENAME}.wav)

;exten => s,3,BackGround(for-quality-purposes)
;exten => s,4,BackGround(this-call-may-be)
;exten => s,5,BackGround(recorded)

; This macro is for dev purposes and just dumps channel/app variables. Useful when designing new contexts.
[macro-dumpvars]
exten => s,1,Noop(ACCOUNTCODE=${ACCOUNTCODE})
exten => s,2,Noop(ANSWEREDTIME=${ANSWEREDTIME})
exten => s,3,Noop(BLINDTRANSFER=${BLINDTRANSFER})
exten => s,4,Noop(CALLERID=${CALLERID(all)})
exten => s,5,Noop(CALLERID(name)=${CALLERID(name)})
exten => s,6,Noop(CALLERID(number)=${CALLERID(number)})
exten => s,7,Noop(CALLINGPRES=${CALLINGPRES})
exten => s,8,Noop(CHANNEL=${CHANNEL})
exten => s,9,Noop(CONTEXT=${CONTEXT})
exten => s,10,Noop(DATETIME=${DATETIME})
exten => s,11,Noop(DIALEDPEERNAME=${DIALEDPEERNAME})
exten => s,12,Noop(DIALEDPEERNUMBER=${DIALEDPEERNUMBER})
exten => s,13,Noop(DIALEDTIME=${DIALEDTIME})
exten => s,14,Noop(DIALSTATUS=${DIALSTATUS})
exten => s,15,Noop(DNID=${DNID})
exten => s,16,Noop(EPOCH=${EPOCH})
exten => s,17,Noop(EXTEN=${EXTEN})
exten => s,18,Noop(HANGUPCAUSE=${HANGUPCAUSE})
exten => s,19,Noop(INVALID_EXTEN=${INVALID_EXTEN})
exten => s,20,Noop(LANGUAGE=${LANGUAGE})
exten => s,21,Noop(MEETMESECS=${MEETMESECS})
exten => s,22,Noop(PRIORITY=${PRIORITY})
exten => s,23,Noop(RDNIS=${RDNIS})
exten => s,24,Noop(SIPDOMAIN=${SIPDOMAIN})
exten => s,25,Noop(SIP_CODEC=${SIP_CODEC})
exten => s,26,Noop(SIPCALLID=${SIPCALLID})
exten => s,27,Noop(SIPUSERAGENT=${SIPUSERAGENT})
exten => s,29,Noop(TXTCIDNAME=${TXTCIDNAME})
exten => s,30,Noop(UNIQUEID=${UNIQUEID})
exten => s,31,Noop(TOUCH_MONITOR=${TOUCH_MONITOR})
exten => s,32,Noop(MACRO_CONTEXT=${MACRO_CONTEXT})
exten => s,33,Noop(MACRO_EXTEN=${MACRO_EXTEN})
exten => s,34,Noop(MACRO_PRIORITY=${MACRO_PRIORITY})

[macro-user-logon]
; check device type
;
exten => s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)})
exten => s,n,GotoIf($["${DEVICETYPE}" = “fixed”]?s-FIXED,1)
; get user’s extension
;
exten => s,n,Set(AMPUSER=${ARG1})
exten => s,n,GotoIf($["${AMPUSER}" != “”]?gotpass)
exten => s,n,Playback(please-enter-your&extension)
exten => s,n,Read(AMPUSER,then-press-pound)
; get user’s password and authenticate
;
exten => s,n(gotpass),Set(AMPUSERPASS=${DB(AMPUSER/${AMPUSER}/password)})
exten => s,n,GotoIf($[${LEN(${AMPUSERPASS})} = 0]?s-NOPASSWORD,1)
; do not continue if the user has already logged onto this device
;
exten => s,n,Set(DEVICEUSER=${DB(DEVICE/${CALLERID(number)}/user)})
exten => s,n,GotoIf($["${DEVICEUSER}" = “${AMPUSER}”]?s-ALREADYLOGGEDON,1)
exten => s,n,Authenticate(${AMPUSERPASS})
exten => s,n,DeadAGI(user_login_out.agi,login,${CALLERID(number)},${AMPUSER})
exten => s,n,Playback(vm-goodbye)

exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged into)
exten => s-FIXED,n,Playback(ha/phone)
exten => s-FIXED,n,SayDigits(${CALLERID(number)})
exten => s-FIXED,n,Playback(is-curntly-unavail&vm-goodbye)
exten => s-FIXED,n,Hangup ;TODO should play msg indicated device cannot be logged into

exten => s-ALREADYLOGGEDON,1,NoOp(This device has already been logged into by this user)
exten => s-ALREADYLOGGEDON,n,Playback(vm-goodbye)
exten => s-ALREADYLOGGEDON,n,Hangup ;TODO should play msg indicated device is already logged into

exten => s-NOPASSWORD,1,NoOp(This extension does not exist or no password is set)
exten => s-NOPASSWORD,n,Playback(an-error-has-occured&vm-goodbye)
exten => s-NOPASSWORD,n,Hangup ;TODO should play msg indicated device is already logged into

[macro-user-logoff]
; check device type
;
exten => s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)})
exten => s,n,GotoIf($["${DEVICETYPE}" = “fixed”]?s-FIXED,1)
exten => s,n,DeadAGI(user_login_out.agi,logout,${CALLERID(number)})
exten => s,n(done),Playback(vm-goodbye)

exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged out of)
exten => s-FIXED,n,Playback(an-error-has-occured&vm-goodbye)
exten => s-FIXED,n,Hangup ;TODO should play msg indicated device cannot be logged into

; Privacy Manager Macro makes sure that any calls that don’t pass the privacy manager are presented
; with congestion since there have been observed cases of the call continuing if not stopped with a
; congestion, and this provides a slightly more friendly ‘sorry’ message in case the user is
; legitamately trying to be cooperative.
;
; Note: the following options are configurable in privacy.conf:
;
; maxretries = 3 ; default value, number of retries before failing
; minlength = 10 ; default value, number of digits to be accepted as valid CID
;
[macro-privacy-mgr]
exten => s,1,Set(KEEPCID=${CALLERID(num)})
exten => s,n,GotoIf($[“foo${CALLERID(num):0:1}”=“foo+”]?CIDTEST2:CIDTEST1)
exten => s,n(CIDTEST1),Set(TESTCID=${MATH(1+${CALLERID(num)})})
exten => s,n,Goto(TESTRESULT)
exten => s,n(CIDTEST2),Set(TESTCID=${MATH(1+${CALLERID(num):1})})
exten => s,n(TESTRESULT),GotoIf($[“foo${TESTCID}”=“foo”]?CLEARCID:PRIVMGR)
exten => s,n(CLEARCID),Set(CALLERID(num)=)
exten => s,n(PRIVMGR),PrivacyManager()
exten => s,n,GotoIf($["${PRIVACYMGRSTATUS}"=“FAILED”]?fail)
exten => s,n,SetCallerPres(allowed_passed_screen); stop gap until app_privacy.c clears unavailble bit
exten => s,PRIVMGR+101(fail),Noop(STATUS: ${PRIVACYMGRSTATUS} CID: ${CALLERID(num)} ${CALLERID(name)} CALLPRES: ${CALLLINGPRES})
exten => s,n,Playback(sorry-youre-having-problems)
exten => s,n,Playback(goodbye)
exten => s,n,Playtones(congestion)
exten => s,n,Congestion(5)

; Text-To-Speech related macros
; These all follow common actions. First try to playback a file “tts/custom-md5”
; where “md5” is the md5() of whatever is going to be played. If that doesn’t exist,
; try to playback using macro-tts-sayXXXXX (where XXXXX is text/digits/etc, same as
; the macro below). If that macro exits with MACRO_OFFSET=100, then it’s done,
; therwise, fallback to the default asterisk method.
;
; say text is purely for text-to-speech, there is no fallback
[macro-saytext]
exten => s,1,Noop(Trying custom SayText playback for “${ARG1}”)
exten => s,n,Playback(tts/custom-${MD5(${ARG1})})
exten => s,n,GotoIf($["${PLAYBACKSTATUS}"=“SUCCESS”]?done)
; call tts-saytext. This should set MACRO_OFFSET=101 if it was successful
exten => s,n(tts),Macro(tts-saytext,${ARG1},${ARG2},${ARG3})
exten => s,n,Noop(No text-to-speech handler for SayText, cannot say “${ARG1}”)
exten => s,n,Goto(done)
exten => s,tts+101,Noop(tts handled saytext)

; say name is for saying names typically, but fallsback to using SayAlpha
; (saying the word letter-by-letter)
[macro-sayname]
exten => s,1,Noop(Trying custom SayName playback for “${ARG1}”)
exten => s,n,Playback(tts/custom-${MD5(${ARG1})})
exten => s,n,GotoIf($["${PLAYBACKSTATUS}"=“SUCCESS”]?done)
; call tts-sayalpha. This should set MACRO_OFFSET=101 if it was successful
exten => s,n(tts),Macro(tts-sayalpha,${ARG1},${ARG2},${ARG3})
exten => s,n,SayAlpha(${ARG1})
exten => s,n,Goto(done)
exten => s,tts+101,Noop(tts handled sayname)

; Say number is for saying numbers (eg “one thousand forty six”)
[macro-saynumber]
exten => s,1,Noop(Trying custom SayNumber playback for “${ARG1}”)
exten => s,n,Playback(tts/custom-${MD5(${ARG1})})
exten => s,n,GotoIf($["${PLAYBACKSTATUS}"=“SUCCESS”]?done)
; call tts-saynumber. This should set MACRO_OFFSET=101 if it was successful
exten => s,n(tts),Macro(tts-saynumber,${ARG1},${ARG2},${ARG3})
exten => s,n,SayNumber(${ARG1})
exten => s,n,Goto(done)
exten => s,tts+101,Noop(tts handled saynumber)

; Say digits is for saying digits one-by-one (eg, “one zero four six”)
[macro-saydigits]
exten => s,1,Noop(Trying custom SayDigits playback for “${ARG1}”)
exten => s,n,Playback(tts/custom-${MD5(${ARG1})})
exten => s,n,GotoIf($["${PLAYBACKSTATUS}"=“SUCCESS”]?done)
; call tts-saydigits. This should set MACRO_OFFSET=101 if it was successful
exten => s,n(tts),Macro(tts-saydigits,${ARG1},${ARG2},${ARG3})
exten => s,n,SayDigits(${ARG1})
exten => s,n,Goto(done)

;
; ############################################################################
; Inbound Contexts [from]
; ############################################################################

[from-sip-external]
;give external sip users congestion and hangup
; Yes. This is really meant to be _. - I know asterisk whinges about it, but
; I do know what I’m doing. This is correct.
exten => _.,1,NoOp(Received incoming SIP connection from unknown peer to ${EXTEN})
exten => _.,n,Set(DID=${IF($["${EXTEN:1:2}"=""]?s:${EXTEN})})
exten => _.,n,Goto(s,1)
exten => s,1,GotoIf($["${ALLOW_SIP_ANON}"=“yes”]?from-trunk,${DID},1)
exten => s,n,Set(TIMEOUT(absolute)=15)
exten => s,n,Answer
exten => s,n,Wait(2)
exten => s,n,Playback(ss-noservice)
exten => s,n,Playtones(congestion)
exten => s,n,Congestion(5)
exten => h,1,NoOp(Hangup)
exten => i,1,NoOp(Invalid)
exten => t,1,NoOp(Timeout)

[from-internal-xfer]
; applications are now mostly all found in from-internal-additional in _custom.conf
include => parkedcalls
include => from-internal-custom
;allow phones to dial other extensions
include => ext-fax
;allow phones to access generated contexts
;
; MODIFIED (PL)
;
; Currently the include for findmefollow is being auto-generated before ext-local which is the desired behavior.
; However, I haven’t been able to do anything that I know of to force this. We need to determine if it should
; be hardcoded into here to make sure it doesn’t change with some configuration. For now I will leave it out
; until we can discuss this.
;
include => ext-local-confirm
include => findmefollow-ringallv2
include => from-internal-additional
; This causes grief with ‘#’ transfers, commenting out for the moment.
; include => bad-number
exten => s,1,Macro(hangupcall)
exten => h,1,Macro(hangupcall)

[from-internal]
include => from-internal-xfer
include => bad-number

[from-zaptel]
exten => _X.,1,Set(DID=${EXTEN})
exten => _X.,n,Goto(s,1)
exten => s,1,NoOp(Entering from-zaptel with DID == ${DID})
; Some trunks require a RINGING be sent before an Answer.
exten => s,n,Ringing()
; If ($did == “”) { $did = “s”; }
exten => s,n,Set(DID=${IF($["${DID}"= “”]?s:${DID})})
exten => s,n,NoOp(DID is now ${DID})
exten => s,n,GotoIf($["${CHANNEL:0:3}"=“Zap”]?zapok:notzap)
exten => s,n(notzap),Goto(from-pstn,${DID},1)
; If there’s no ext-did,s,1, that means there’s not a no did/no cid route. Hangup.
exten => s,n,Macro(hangup)
exten => s,n(zapok),NoOp(Is a Zaptel Channel)
exten => s,n,Set(CHAN=${CHANNEL:4})
exten => s,n,Set(CHAN=${CUT(CHAN,-,1)})
exten => s,n,Macro(from-zaptel-${CHAN},${DID},1)
; If nothing there, then treat it as a DID
exten => s,n,NoOp(Returned from Macro from-zaptel-${CHAN})
exten => s,n,Goto(from-pstn,${DID},1)
exten => fax,1,Goto(ext-fax,in_fax,1)

;------------------------------------------------------------------------
; [macro-setmusic]
;------------------------------------------------------------------------
; CONTEXT: macro-setmusic
; PURPOSE: to turn off moh on routes where it is not desired
;
;------------------------------------------------------------------------
[macro-setmusic]
exten => s,1,NoOp(Setting Outbound Route MoH To: ${ARG1})
exten => s,2,SetMusicOnHold(${ARG1})
;------------------------------------------------------------------------

; ##########################################
; ## Ring Groups with Confirmation macros ##
; ##########################################
; Used by followme and ringgroups

;------------------------------------------------------------------------
; [macro-dial-confirm]
;------------------------------------------------------------------------
; This has now been incorporated into dialparties. It still only works with ringall
; and ringall-prim strategies. Have not investigated why it doesn’t work with
; hunt and memory hunt.
;
;------------------------------------------------------------------------
[macro-dial-confirm]
; This was written to make it easy to use macro-dial-confirm instead of macro-dial in generated dialplans.
; This takes the same paramaters, with an additional paramater of the ring group Number
; ARG1 is the timeout
; ARG2 is the DIAL_OPTIONS
; ARG3 is a list of xtns to call - 203-222-240-123123123#-211
; ARG4 is the ring group number

; This sets a unique value to indicate that the channel is ringing. This is used for warning slow
; users that the call has already been picked up.
;
exten => s,1,Set(DB(RG/${ARG4}/${CHANNEL})=RINGING)

; We need to keep that channel variable, because it’ll change when we do this dial, so set it to
; fallthrough to every sibling.
;
exten => s,n,Set(__UNIQCHAN=${CHANNEL})

; The calling ringgroup should have set RingGroupMethod appropriately. We need to set two
; additional parameters:
;
; USE_CONFIRMATION, RINGGROUP_INDEX
;
; Thse are passed to inform dialparties to place external calls through the [grps] context
;
exten => s,n,Set(USE_CONFIRMATION=TRUE)
exten => s,n,Set(RINGGROUP_INDEX=${ARG4})
exten => s,n,Set(ARG4=) ; otherwise it gets passed to dialparties.agi which processes it (prob bug)

exten => s,n,Macro(dial,${ARG1},${ARG2},${ARG3})

; delete the variable, if we are here, we are done trying to dial and it may have been left around
;
exten => s,n,DBDel(RG/${RINGGROUP_INDEX}/${CHANNEL})
exten => s,n,Set(USE_CONFIRMATION=)
exten => s,n,Set(RINGGROUP_INDEX=)
;------------------------------------------------------------------------

;------------------------------------------------------------------------
; [macro-auto-confirm]
;------------------------------------------------------------------------
; This macro is called from ext-local-confirm to auto-confirm a call so that other extensions
; are aware that the call has been answered.
;
;------------------------------------------------------------------------
[macro-auto-confirm]
exten => s,1,Set(__MACRO_RESULT=)
exten => s,n,Set(__CWIGNORE=)
exten => s,n,DBDel(${BLKVM_OVERRIDE})
exten => s,n,DBDel(RG/${ARG1}/${UNIQCHAN})

;------------------------------------------------------------------------
; [macro-auto-blkvm]
;------------------------------------------------------------------------
; This macro is called for any extension dialed form a queue, ringgroup
; or followme, so that the answering extension can clear the voicemail block
; override allow subsequent transfers to properly operate.
;
;------------------------------------------------------------------------
[macro-auto-blkvm]
exten => s,1,Set(__MACRO_RESULT=)
exten => s,n,Set(__CWIGNORE=)
exten => s,n,DBDel(${BLKVM_OVERRIDE})

;------------------------------------------------------------------------
; [ext-local-confirm]
;------------------------------------------------------------------------
; If call confirm is being used in a ringgroup, then calls that do not require confirmation are sent
; to this extension instead of straight to the device.
;
; The sole purpose of sending them here is to make sure we run Macro(auto-confirm) if this
; extension answers the line. This takes care of clearing the database key that is used to inform
; other potential late comers that the extension has been answered by someone else.
;
; ALERT_INFO is deprecated in Asterisk 1.4 but still used throughout the FreePBX dialplan and
; usually set by dialparties.agi. This allows ineritance. Since no dialparties.agi here, set the
; header if it is set.
;
;------------------------------------------------------------------------
[ext-local-confirm]
exten => _LC-.,1,Noop(IN ext-local-confirm with - RT: ${RT}, RG_IDX: ${RG_IDX})
exten => _LC-.,n,GotoIf($[“x${ALERT_INFO}”=“x”]?godial)
exten => _LC-.,n,SIPAddHeader(Alert-Info: ${ALERT_INFO})
exten => _LC-.,n(godial),dial(${DB(DEVICE/${EXTEN:3}/dial)},${RT},M(auto-confirm^${RG_IDX})${DIAL_OPTIONS})

;------------------------------------------------------------------------
; [macro-confirm]
;------------------------------------------------------------------------
; CONTEXT: macro-confirm
; PURPOSE: added default message if none supplied
;
; Follom-Me and Ringgroups provide an option to supply a message to be
; played as part of the confirmation. These changes have added a default
; message if none is supplied.
;
;------------------------------------------------------------------------
[macro-confirm]
exten => s,1,Set(LOOPCOUNT=0)
exten => s,n,Noop(CALLCONFIRMCID: ${CALLCONFIRMCID})

; We set ABORT rather than CONTINUE, as we want the server to forget about this channel
; if it’s declined, hung up, or timed out. We don’t want it to continue on to the next
; step in the dialplan, which could be anything!
exten => s,n,Set(__MACRO_RESULT=ABORT)

; ARG1 is the announcement to play to tell the user that they’ve got a call they need
; to confirm. Something along the lines of 'You have an incoming call. Press 1 to accept, 9 to reject’
exten => s,n,Set(MSG1=${IF($[“foo${ARG1}” != “foo”]?${ARG1}:“incoming-call-1-accept-2-decline”)})
exten => s,n(start),Read(INPUT,${MSG1},1,1,5)

; So. We’ve now read something, or nothing. We should check to make sure that the call hasn’t
; already been answered by someone else. If it has, send this call to toolate
exten => s,n,GotoIf(${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}?check:toolate)

; We passed that test, so it means the call hasn’t been answered. Has this user pushed 1? If so,
; then go to OK.
exten => s,n(check),GotoIf($["${INPUT}"=“1”]?ok)

; If they’ve pushed 9, then they definately don’t want the call. Just pretend there was no response
; and go to noanswer (or 2 since that will be default for asterisk)
exten => s,n,GotoIf($["${INPUT}"=“9”]?noanswer)
exten => s,n,GotoIf($["${INPUT}"=“2”]?noanswer)
exten => s,n,GotoIf($["${INPUT}"=“3”]?playcid)

; Increment LOOPCOUNT, and check to make sure we haven’t played it 5 times by now. We assume that
; the person is able to push ‘1’ in a reasonably short time.
exten => s,n,Set(LOOPCOUNT=$[ ${LOOPCOUNT} + 1 ])
exten => s,n,GotoIf($[ ${LOOPCOUNT} < 5 ]?start)

; If we’re here, that means we’ve played it MORE than 5 times. Set __MACRO_RESULT=ABORT, well, just
; coz, and goto fin, which is the last line, meaning it returns to the previous Dial, and pretends as
; if nothing has happened.
exten => s,n(noanswer),Set(__MACRO_RESULT=ABORT)
exten => s,n,Goto(fin)

; Test play callerid
;
exten => s,n(playcid),Noop(Playing CID: ${CALLCONFIRMCID})
exten => s,n,SayDigits(${CALLCONFIRMCID})
exten => s,n,Goto(start)

; If we’re here, it’s because the call was already accepted by someone else.
exten => s,n(toolate),Set(MSG2=${IF($[“foo${ARG2}” != “foo”]?${ARG2}:“incoming-call-no-longer-avail”)})
exten => s,n,Playback(${MSG2})
exten => s,n,Goto(noanswer)

; If we made it here, it’s because the call WAS accepted, AND it’s still ringing. We delete the
; database entry (so that the DB_EXISTS line above will trigger a ‘toolate’ jump), and set the
; MACRO_RESULT variable to NOTHING. This is the magic string that joins both legs of the call together
exten => s,n(ok),DBDel(RG/${ARG3}/${UNIQCHAN})
exten => s,n,DBDel(${BLKVM_OVERRIDE})
exten => s,n,Set(__MACRO_RESULT=)

; The end.
exten => s,n(fin),NoOp(Finished)
exten => h,1,Noop(Hangup Extension in macro-confirm)
exten => h,n,Macro(hangupcall)

;------------------------------------------------------------------------

;------------------------------------------------------------------------
; [findmefollow-ringallv2]
;------------------------------------------------------------------------
; This context, to be included in from-internal, implements the PreRing part of findmefollow
; as well as the GroupRing part. It also communicates between the two so that if DND is set
; on the primary extension, and mastermode is enabled, then the other extensions will not ring
;
;------------------------------------------------------------------------
[findmefollow-ringallv2]
exten => _FMPR-.,1,Noop(In FMPR ${FMGRP} with ${EXTEN:5})
exten => _FMPR-.,n,Set(RingGroupMethod=)
exten => _FMPR-.,n,Set(USE_CONFIRMATION=)
exten => _FMPR-.,n,Set(RINGGROUP_INDEX=)
exten => _FMPR-.,n,Macro(simple-dial,${EXTEN:5},${FMREALPRERING})
exten => _FMPR-.,n,GotoIf($["${DIALSTATUS}" != “BUSY”]?nodnd)
exten => _FMPR-.,n,Set(DB(FM/DND/${FMGRP}/${FMUNIQUE})=DND)
exten => _FMPR-.,n(nodnd),Noop(Ending FMPR ${FMGRP} with ${EXTEN:5} and dialstatus ${DIALSTATUS})
exten => _FMPR-.,n,Hangup()

exten => _FMGL-.,1,Noop(In FMGL ${FMGRP} with ${EXTEN:5})
exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = “DND”]?dodnd)
exten => _FMGL-.,n,Wait(1)
exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = “DND”]?dodnd)
exten => _FMGL-.,n,Wait(1)
exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = “DND”]?dodnd)
exten => _FMGL-.,n,Wait(${FMPRERING})
exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = “DND”]?dodnd)
exten => _FMGL-.,n,DBDel(FM/DND/${FMGRP}/${FMUNIQUE})
exten => _FMGL-.,n(dodial),Macro(dial,${FMGRPTIME},${DIAL_OPTIONS},${EXTEN:5})
exten => _FMGL-.,n,Noop(Ending FMGL ${FMGRP} with ${EXTEN:5} and dialstatus ${DIALSTATUS})
exten => _FMGL-.,n,Hangup()
exten => _FMGL-.,n+10(dodnd),DBDel(FM/DND/${FMGRP}/${FMUNIQUE})
exten => _FMGL-.,n,GotoIf($["${FMPRIME}" = “FALSE”]?dodial)
exten => _FMGL-.,n,Noop(Got DND in FMGL ${FMGRP} with ${EXTEN:5} in ${RingGroupMethod} mode, aborting)
exten => _FMGL-.,n,Hangup()

;------------------------------------------------------------------------

; ############################################################################
; Extension Contexts [ext]
; ############################################################################

[ext-fax]
exten => s,1,Answer
exten => s,2,Goto(in_fax,1)
exten => in_fax,1,StopPlayTones
exten => in_fax,2,GotoIf($["${FAX_RX}" = “system”]?3:analog_fax,1)
exten => in_fax,3,Macro(faxreceive)
exten => in_fax,4,Hangup
exten => analog_fax,1,GotoIf($["${FAX_RX}" = “disabled”]?4:2) ;if fax is disabled, just hang up
exten => analog_fax,2,Set(DIAL=${DB(DEVICE/${FAX_RX}/dial)});
exten => analog_fax,3,Dial(${DIAL},20,d)
exten => analog_fax,4,Hangup
;exten => out_fax,1,wait(7)
exten => out_fax,1,txfax(${TXFAX_NAME},caller)
exten => out_fax,2,Hangup
exten => h,1,system(/var/lib/asterisk/bin/fax-process.pl --to ${EMAILADDR} --from ${FAX_RX_FROM} --subject “Fax from ${URIENCODE(${CALLERID(number)})} ${URIENCODE(${CALLERID(name)})}” --attachment fax_${URIENCODE(${CALLERID(number)})}.pdf --type application/pdf --file ${FAXFILE});
exten => h,2,Hangup()

;this is where parked calls go if they time-out. Should probably re-ring
[default]
include => ext-local
exten => s,1,Playback(vm-goodbye)
exten => s,2,Macro(hangupcall)

;Sangoma SS7 Outbound context
;Place call on ss7 woomera channel
;==================================

[outb]
exten => _X.,1,noop
;exten => _X.,n,SetCallerID(${CALLERID(num)} <${CALLERID(name)}>)
;exten => _X.,n,Dial(WOOMERA/g1/${EXTEN}|60|o,30)
exten => _X.,n,Dial(WOOMERA/g1/${EXTEN}|60|o)
exten => _X.,n,Hangup

;Sangoma SS7 Incoming Contexts
;The number beside the context name indicates
;the ss7 trunk group.
;====================================

[sangoma1]
exten => _X.,1,noop
exten => _X.,n,Playback(demo-congrats)
;exten => _X.,n,Goto(1)
exten => _X.,n,Hangup

[sangoma2]
exten => _X.,1,noop
exten => _X.,n,Playback(demo-congrats)
;exten => _X.,n,Goto(1)
exten => _X.,n,Hangup

[sangoma3]
exten => _X.,1,noop
exten => _X.,n,Playback(demo-congrats)
;exten => _X.,n,Goto(1)
exten => _X.,n,Hangup

;Sangoma BRI Outbound context
;Place call on bri woomera channel
;==================================

[outb-bri]
exten => _X.,1,noop
;exten => _X.,n,SetCallerID(${CALLERID(num)} <${CALLERID(name)}>)
exten => _X.,n,Dial(WOOMERA/g1/${EXTEN}|60|o,30)
exten => _X.,n,Hangup

;Sangoma BRI Incoming Contexts
;By default, the wancfg_smg utility will add
; 1. TE spans to the from-pstn context
; 2. NT spans to the from-internal context

[from-pstn]
exten => _X.,1,noop
exten => _X.,n,Playback(demo-congrats)
;exten => _X.,n,Goto(1)
exten => _X.,n,Hangup

[from-internal]
exten => _X.,1,noop
exten => _X.,n,Playback(demo-congrats)
;exten => _X.,n,Goto(1)
exten => _X.,n,Hangup

This is a copy of my Woomera.conf

[settings]
debug=2

[default]
host=localhost
port=42420
audio_ip=127.0.0.1
default_context=sangoma
debug=2
dtmf_enable=1
jb_enable=0
progress_enable=0

context=from-pstn
group=1