Skip to content

Instantly share code, notes, and snippets.

@lgaetz
Last active April 12, 2024 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lgaetz/4c14829c14eb0a739a216016d9f394b2 to your computer and use it in GitHub Desktop.
Save lgaetz/4c14829c14eb0a739a216016d9f394b2 to your computer and use it in GitHub Desktop.
Feature code to seamlessly bounce an active bridged call between a user’s multiple devices
; FreePBX dialplan for a feature code that can be dialed from an idle device that will immediately bounce
; any active call from any of the the same user's extensions. Primary use case is when a user has multiple
; registered devices they can quickly move the active call between deskphone, to mobile client to desktop client.
;
; License: GNU GPL3+
; latest version: https://gist.github.com/lgaetz/4c14829c14eb0a739a216016d9f394b2
;
; version history 2024-03-22 First commit working
; 2024-03-24 Fix hint and change ext away from _.
[from-internal-custom]
exten => _*37!,hint,PJSIP/${EXTEN:3}&PJSIP/98${EXTEN:3}&PJSIP/99${EXTEN:3}
exten => _*37!,1,Noop(User defined context to seize any active call from dialing user)
exten => _*37!,n,Macro(user-callerid)
exten => _*37!,n,Goto(seize-current-active-call,${AMPUSER},1)
[seize-current-active-call]
exten => _X.,1,Noop(User defined context seize-current-active-call to seize any active call from the dialing user)
; get full list of dialable devices for the user from AstDB
exten => _X.,n,Set(DEVS=${DB(AMPUSER/${AMPUSER}/device)}) ; & delimited list of devices
exten => _X.,n,Set(DEVS=${STRREPLACE(DEVS,&,\,)}) ; comma delimited list of devices
; step thru each device and look for an active channel
exten => _X.,n,While($["${SET(DEV=${POP(DEVS)})}" != ""])
exten => _X.,n,noop(device: ${DEV})
; using a regex of SIP/${EXTEN}- will match both SIP and PJSIP channels, and the trailing - character should
; help to ensure there is only a single match.
exten => _X.,n,set(seize_target=${CHANNELS(SIP/${DEV}-)})
; we don't want the dialing channel to seize itself, so remove current dialing channel from channel list and trim string
exten => _X.,n,Noop(Current channel name: ${CHANNEL})
exten => _X.,n,set(seize_target=${STRREPLACE(seize_target,${CHANNEL},)})
exten => _X.,n,set(seize_target=${STRREPLACE(seize_target, ,)})
; if an active channel is found exit the loop, otherwise loop again
exten => _X.,n,ExecIf($["${seize_target}"!=""]?ExitWhile)
exten => _X.,n,EndWhile()
exten => _X.,n,Bridge(${IMPORT(${CHANNELS(${seize_target})},BRIDGEPEER)})
exten => _X.,n,Macro(hangupcall)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment