Problema
Durante una chiamata si desidera riprodurre un file audio con la digitazione di DTMF.

Soluzione
Per prima cosa iniziamo con la creazione di una nuova applicationmap:
; features.conf
[applicationmap]
play_message => #1,self/caller,Macro(PlayMessage)

Quindi creiamo la nostra Macro() per iniettare l’audio messaggio.
; extensions.conf
[macro-PlayMessage]
exten => s,1,NoOp()
same => n,Set(EncodedChannelToPass=${URIENCODE(${DYNAMIC_PEERNAME})})
same => n,Originate(Local/spy-${EncodedChannelToPass}@whisper-channel/n,exten,whisper-channel,audio,1)

La nostra Macro() chiama tramite un canale locale un altro contesto che esegue l’iniezione audio:
[whisper-channel]
exten => _spy-.,1,NoOp()
same => n,Set(EncodedChannel=${CUT(EXTEN,-,2-3)})
same => n,Set(GROUP(whisper-channel)=${EncodedChannel})
same => n,ExecIf($[${GROUP_COUNT(${EncodedChannel}@whisper-channel)} > 1]?Hangup())
same => n,Set(ChannelToSpy=${URIDECODE(${EncodedChannel})})
same => n,ChanSpy(${ChannelToSpy},wsqEB)
same => n,Hangup()


exten => audio,1,NoOp()
same => n,Answer()
same => n,Wait(0.4)
same => n,Set(VOLUME(TX)=-4)
; Un esempio è restituire il costo corrente della chiamata. Una ricerca in un database o
; webservice sarebbe necessario per rendere i dati dinamici.
;
same => n,SayNumber(7)
same => n,Playback(digits/dollars)
same => n,SayNumber(48)
same => n,Playback(cents)
same => n,Hangup()

E quindi per abilitarlo dobbiamo aggiungere la seguente riga nel dialplan che viene eseguito dal canale che attiverà la riproduzione audio:
exten => _2XX,1,NoOp()
same => n,Set(DYNAMIC_FEATURES=play_message)
same => n,Dial(SIP/${EXTEN},30)

In questo esempio abbiamo configurato il file features.conf definendo la funzione chiamata play_message.
La funzione play_message, alla digitazione (come DTMF) del codice “#1”, esegue la macro PlayMessage.
L’opzione definita come self/caller significa che il canale che effettua la chiamata sarà quello in grado di attivare il codice “#1” e sarà anche il canale che ascolterà l’audio iniettato nella chiamata.

Nel contesto macro-PlayMessage, abbiamo assegnato il nome del canale in cui andremo ad iniettare l’audio nella variabile EncodedChannelToPass. Il nome del canale è ottenuto dalla variabile DYNAMIC_PEERNAME che è stata impostata quando la funzione play_message è stata attivata tramite la sequenza DTMF “#1”.
Abbiamo utilizzato la funzione URIENCODE() perché nel nome del canale c’è sicuramente la / che andrebbe ad interromperebbe
l’esecuzione del comando Originate() per errato nel formato.

L’applicazione Originate() viene utilizzata per attivare la riproduzione dell’audio.
I valori relativi a dove riprodurre l’audio vengono passati tramite l’estensione spy- nel contesto whisper-channel.
Il valore passato a URIENCODE() deriva dalla funzione CUT(), che prende l’estensione e la separa in base al carattere “-“, passando solo il secondo e il terzo campo e assegnandoli alla variabile ChannelToSpy.
Usando la variabile di canale ChannelToSpy, iniettiamo l’audio nel canale usando l’applicazione ChanSpy().

Questi i flag passati all’applicazione ChanSpy():
w: whispering al canale; permette di ascoltare e parlare
s: silenzioso; non riprodurre alcun segnale acustico
q: silenzioso; non riprodurre il tipo di canale
E: uscire dopo la chiusura del bridge
B: effettual whispering su entrambi i canali

Una volta che l’applicazione Originate() ha collegato l’applicazione ChanSpy() al canale richiesto si procede con la riprodurre dell’audio nell’estensione audio all’interno del contesto whisper-channel.
Abbiamo anche abbassato il volume dell’audio usando la funzione VOLUME().

Riferimenti wiki Asterisk 18:

ChanSpy() https://wiki.asterisk.org/wiki/display/AST/Application_ChanSpy
VOLUME() https://wiki.asterisk.org/wiki/display/AST/Function_VOLUME