You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
2.8 KiB
Go

3 years ago
package icsdtmf
import (
"encoding/binary"
"fmt"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
)
type ICSDTMF struct {
rfc2833 *RFC2833
}
func NewICSDTMF() *ICSDTMF {
d := ICSDTMF{rfc2833: nil}
return &d
}
func DTMF(dtmf *ICSDTMF, data interface{}, pcm []byte) (string, *icserror.IcsError) {
switch v := (data).(type) {
case icspacketparser.RTP:
rtp := v
switch rtp.GetPayloadType() { //in band
case icspacketparser.DTMF101: //rtp 101
//fmt.Println("101")
rfc2833, d, derr := dtmfRFC2833(rtp)
if rfc2833.Mark { //if rtp mark, reset old dtmf handle
dtmf.rfc2833 = nil
return "", icserror.ICSERRDTMFCont
}
if derr != icserror.ICSERRDTMFCont {
if dtmf.rfc2833 == nil || !dtmf.rfc2833.isEqual(rfc2833) {
dtmf.rfc2833 = rfc2833
dtmf := fmt.Sprintf("%d", d)
return dtmf, derr
} else {
return "", icserror.ICSERRDTMFCont
}
} else {
return "", derr
}
case icspacketparser.PCMA:
fallthrough
case icspacketparser.G729:
fallthrough
case icspacketparser.PCMU: //bypass
dtmfBypass(pcm)
}
case icspacketparser.SIP: //sip info. rfc2976
}
return "", icserror.ICSERRDTMFFail
}
func (d *ICSDTMF) Reset() {
d.rfc2833 = nil
}
///////////////////////////////////////////////////////////////////////
//RFC 2833 - rtp event
type RFC2833 struct {
Event int
End bool
Volume int
Duration int
Mark bool
}
func dtmfRFC2833(rtp icspacketparser.RTP) (*RFC2833, int, *icserror.IcsError) {
r, err := parseRFC2833(rtp)
if err == icserror.ICSERRDTMFFail {
return nil, -1, err
} else if err == icserror.ICSERRDTMFCont {
return r, -1, err
}
event, err := r.GetDTMF()
return r, event, err
}
func parseRFC2833(rtp icspacketparser.RTP) (*RFC2833, *icserror.IcsError) {
r := RFC2833{}
data := rtp.Payload
r.End = data[1]&0x80 == 0x80
if r.End {
//fmt.Println("RTP Event End?", r.End, data[1], len(data))
r.Event = int(data[0])
//fmt.Println("DTMF :", r.Event)
vol := data[1] << 2
r.Volume = int(vol >> 2)
//fmt.Println("vol", r.Volume, vol, data[1])
dur := binary.BigEndian.Uint16(data[2:])
r.Duration = int(dur)
//fmt.Println("Dur", dur)
} else {
r.Mark = rtp.Mark
return &r, icserror.ICSERRDTMFCont
}
r.Mark = rtp.Mark
return &r, icserror.ICSERRDTMFOK
}
func (r RFC2833) GetDTMF() (int, *icserror.IcsError) {
return r.Event, icserror.ICSERRDTMFOK
}
func (r RFC2833) isEqual(rfc2833 *RFC2833) bool {
if r.Duration == rfc2833.Duration && r.End == rfc2833.End && r.Event == rfc2833.Event && r.Volume == rfc2833.Volume {
return true
}
return false
}
///////////////////////////////////////////////////////////////////////
//bypass - audio
type ByPassDTMF struct {
VoiceBuf []byte
}
func dtmfBypass(data []byte) (string, *icserror.IcsError) {
return "", icserror.ICSERRDTMFFail
}