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 }