Public Class PhoneForm
    Public cfgWrap As SIPPhoneCfgWrap
    Public phoneRunning As Boolean
    Public env As MyGTAPIEnv


    Private Sub PhoneForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        cfgWrap = New SIPPhoneCfgWrap()
        phoneRunning = False
        env = Nothing
        Dim cfg As New CfgForm(cfgWrap)
        If cfg.ShowDialog() = DialogResult.OK Then
            If phoneRunning Then
                FreeSIPServer()
            End If

            InitSIPServer()
        Else
            If Not phoneRunning Then
                InitSIPServer()
            End If
        End If

        tbSipAddr.Text = "8888@sip.pcbest.net"


    End Sub

    Public Sub On_RecvConnected(ByVal ch As Integer)
        env.StopSound()
        'stop the ring tone or ringback tone
        'Send_SetChanInConference(0, -1, 1)
        'Send_SetChanInConference(0, ch, 1)
        env.Send_StartDXAudio(ch)
        'because this is a client phone, we start DirectX audio
        'It is in timer's thread now, because we use timer to process event
        Dim sCodec As String
        Dim nCodec As Integer
        nCodec = env.GetChanAudioCodec(ch)

        sCodec = "unknown"

        Select Case nCodec
            Case 0
                sCodec = "G711-Ulaw"
                Exit Select
            Case 3
                sCodec = "GSM"
                Exit Select
            Case 4
                sCodec = "G723.1"
                Exit Select
            Case 8
                sCodec = "G711-Alaw"
                Exit Select
            Case 18
                sCodec = "G729"
                Exit Select
            Case 98
                sCodec = "G716-32"
                Exit Select
            Case 102
                sCodec = "Speex"
                Exit Select
            Case 103
                sCodec = "iLBC-20ms"
                Exit Select
            Case 104
                sCodec = "iLBC-30ms"
                Exit Select
        End Select

        btnDial.Text = "Answer"
        btnDial.Enabled = False
        btnHungup.Enabled = True
        btnHold.Enabled = True
        btnTransfer.Enabled = True
        lbLineStatus.Text = "Call Connected! " & sCodec
    End Sub

    Public Sub On_RecvOffered(ByVal ch As Integer, ByVal sCaller As String, ByVal sCallee As String, ByVal sDestAddr As String, ByVal sViaAddr As String, ByVal sFromIP As String, _
     ByVal nFromPort As UShort)
        tbSipAddr.Text = sCaller
        btnDial.Text = "Answer"
        btnDial.Enabled = True
        btnHungup.Enabled = True
        btnHold.Enabled = False
        btnTransfer.Enabled = False
        lbLineStatus.Text = "New Call from " & sCaller

        env.StopSound()
        env.PlayLocalRingSound()

    End Sub

    Public Sub On_RecvDialing(ByVal ch As Integer, ByVal sCaller As String, ByVal sCallee As String)
        btnDial.Text = "Dial"
        btnDial.Enabled = False
        btnHungup.Enabled = True
        btnHold.Enabled = False
        btnTransfer.Enabled = False
        lbLineStatus.Text = "Dialing"
    End Sub

    Public Sub On_RecvRinging(ByVal ch As Integer)
        btnDial.Text = "Dial"
        btnDial.Enabled = False
        btnHungup.Enabled = True
        btnHold.Enabled = False
        btnTransfer.Enabled = False
        lbLineStatus.Text = "Remote side ringing"

        env.StopSound()
        env.PlayRemoteRingSound()
    End Sub

    Public Sub On_RecvIdle(ByVal ch As Integer, ByVal code As Integer, ByVal desc As String)
        btnDial.Text = "Dial"
        btnDial.Enabled = True
        btnHungup.Enabled = False
        btnHold.Enabled = False
        btnTransfer.Enabled = False
        lbLineStatus.Text = "LINE IDLE"

        env.StopSound()

        'Send_SetChanInConference(0, -1, 0)
        'Send_SetChanInConference(0, ch, 0)
    End Sub

    Public Sub On_RecvRegStatus(ByVal user_id As Integer, ByVal status As Integer, ByVal regtime As Integer)
        lbSIPAcctStatus.Text = env.CFG_GetValue("gtsrv.sip.reg1.username", "")
        If lbSIPAcctStatus.Text.Length > 0 Then
            If status = 0 Then
                lbSIPAcctStatus.Text += " XXX(Not Registered)"
            End If
        Else
            lbSIPAcctStatus.Text = "No SIP Account"
        End If
    End Sub

    Public Sub On_RecvHolding(ByVal ch As Integer, ByVal hold_on As Integer)
        Dim chan As GTAPIASM.GTAPIChan

        chan = env.GetChannel(0)
		
		If hold_on = 1 Then
            env.Send_StopDXAudio(ch)
		Else
            env.Send_StartDXAudio(ch)
		End If
		

        If chan.ch_status = GTAPIASM.GTAPI_CHANNEL_STATE.CONNECTED Then
			btnHold.Text = "Hold"
            btnHold.Enabled = True
            btnTransfer.Enabled = True
        End If

        If chan.ch_status = GTAPIASM.GTAPI_CHANNEL_STATE.HOLDING Then
			btnHold.Text = "Unhold"
            btnHold.Enabled = True
            btnTransfer.Enabled = False
        End If

        If chan.ch_status = GTAPIASM.GTAPI_CHANNEL_STATE.BE_HOLDED Then
            btnHold.Enabled = False
            btnTransfer.Enabled = False
        End If
    End Sub

    Public Function InitSIPServer() As Boolean
        If phoneRunning Then
            Return True
        End If

        env = New MyGTAPIEnv()
        env.mainForm = Me
        env.CreateEnv()
        env.SetMainWnd(Handle.ToInt32())

        env.CFG_SetValue("gtsrv.sip.server.model", "0")

        If cfgWrap.Protocol = 1 Then '0(UDP) is the default setting, no need to set
            'here note, for this tag, 1 = UDP, 2 = TCP, And 3 = BOTH, "4" = SIP TLS(SIP Port +1)
            '"5" = SIP TLS & UDP,   "6" = SIP TLS & TCP,  "7" = SIP TLS & UDP & TCP
            env.CFG_SetValue("gtsrv.sip.protocol", "2")
        ElseIf cfgWrap.Protocol = 2 Then 'TLS
            env.CFG_SetValue("gtsrv.sip.protocol", "5") 'TLS + UDP(default)
            env.CFG_SetValue("gtsrv.sip.ssl.type", "3")
            'SIPs enabled. need to set private key fields
            env.CFG_SetValue("gtsrv.sip.ssl.cert.file", Application.StartupPath & "\cert.pem")
            env.CFG_SetValue("gtsrv.sip.ssl.key.file", Application.StartupPath & "\key.pem")
        End If

        env.CFG_SetValue("gtsrv.srtp.type", "1") 'SRTP type 1, auto

        'SIP IP Address you want to use on local
        'Leave it unset if you want to listen on all the network interface
        'CFG_SetValue("gtsrv.sip.ip.address", "");

        'SIP Port, default 5060
        env.CFG_SetValue("gtsrv.sip.ip.port", cfgWrap.SIPPort.ToString())

        'RTP PORT
        env.CFG_SetValue("gtsrv.sip.rtpstartrange", cfgWrap.RTPPort.ToString())
        'env.CFG_SetValue("gtsrv.sip.rtpendrange", "18800")

        'Log
        env.CFG_SetValue("gtsrv.log.level", "4")

        env.CFG_SetValue("gtsrv.log.filename", Application.StartupPath + "\\vbsipphone.txt")

        'Prefered codec list
        env.CFG_SetValue("gtsrv.sip.prefered.codec", cfgWrap.AudioCodecs)
        'env.CFG_SetValue("gtsrv.sip.prefered.video.codec", "34,115,124")

        'NAT or STUN
        If cfgWrap.StunServer.Length > 0 Then
            env.CFG_SetValue("gtsrv.sip.stun.server", cfgWrap.StunServer)
        Else
            env.CFG_SetValue("gtsrv.sip.use.nat.addr", If(cfgWrap.UseNATAddr, "1", "0"))
        End If

        'JB buffer and dirctX buffer settings, DO NOT change
        'env.CFG_SetValue("gtsrv.sip.jb.min.delay", "0")
        'env.CFG_SetValue("gtsrv.sip.jb.max.delay", "5")
        'env.CFG_SetValue("gtsrv.sip.jb.adaptive", "0")
        'env.CFG_SetValue("gtsrv.sip.jb.get.all.data", "1")
        'env.CFG_SetValue("gtsrv.sip.dx.playback.delay", "2")

        'channnel numbers, here we only use 1 channel
        env.CFG_SetValue("gtsrv.sip.boardnum.per.server", "1")
        env.CFG_SetValue("gtsrv.sip.spannum.per.board", "1")
        env.CFG_SetValue("gtsrv.sip.channum.per.span", "1")

        'define inbound and outbound channels, NOT USEFUL ANYMORE. DO NOT USE
        'env.CFG_SetValue("gtsrv.channel.inbound", "0-3");
        'env.CFG_SetValue("gtsrv.channel.outbound", "4-15");

        'Internal communication port
        env.CFG_SetValue("gtsrv.net.port", "7486")
        'any port you like

        'conference room
        'env.CFG_SetValue("gtsrv.sip.conference.room", "1")

        'Configuration file, if you want to define parameters in a file
        'env.CFG_SetValue(GTSRV_CFG_FILENAME, "GTSimpelPhone.ini");

        'Application name, it is related to sdk licence
        'Please contact PCBest Network(www.pcbest.net) to get licence info
        'env.SetAppName("GTSIPSimplePhone");
        'env.CFG_SetValue("gtsrv.sip.conference.room", "1")

        'define outbound route, leave them unset if you don't know
        'env.CFG_SetValue("gtsrv.sip.outbound.via.type", "0");
        'env.CFG_SetValue("gtsrv.sip.outbound.via.proxy", "");

        'set sip client user info ***** If you want to take incoming calls, you must set this value,
        ' or you can only answer calls by your IP address
        'you must get an account from sip service provider first

        If cfgWrap.DisplayName.Length > 0 AndAlso cfgWrap.UserName.Length > 0 AndAlso cfgWrap.Domain.Length > 0 AndAlso cfgWrap.Password.Length > 0 Then
            env.CFG_SetValue("gtsrv.sip.reg.client.num", "1")
            env.CFG_SetValue("gtsrv.sip.reg1.displayname", cfgWrap.DisplayName)
            env.CFG_SetValue("gtsrv.sip.reg1.username", cfgWrap.UserName)
            env.CFG_SetValue("gtsrv.sip.reg1.domain", cfgWrap.Domain)
            env.CFG_SetValue("gtsrv.sip.reg1.proxy", cfgWrap.Domain)
            env.CFG_SetValue("gtsrv.sip.reg1.authorization", cfgWrap.UserName)
            env.CFG_SetValue("gtsrv.sip.reg1.password", cfgWrap.Password)
            env.CFG_SetValue("gtsrv.sip.reg1.expire", "3600")
            If cfgWrap.RegisterDomain Then
                env.CFG_SetValue("gtsrv.sip.reg1.register", "1")
            Else
                env.CFG_SetValue("gtsrv.sip.reg1.register", "0")
            End If

            If cfgWrap.Protocol = 1 Then '0(UDP) is the default setting, no need to set
                env.CFG_SetValue("gtsrv.sip.reg1.prot", "1")
            ElseIf cfgWrap.Protocol = 2 Then '2 TLS, the remote SIP account support TLS registration
                env.CFG_SetValue("gtsrv.sip.reg1.prot", "2") '2 means TLS
                env.CFG_SetValue("gtsrv.sip.reg1.srtp", "1") 'use srtp for the call
            End If

        End If

        If (cfgWrap.UserName.Length > 0) Then
            lbSIPAcctStatus.Text = env.CFG_GetValue("gtsrv.sip.reg1.username", "") & " XXX"
        Else
            lbSIPAcctStatus.Text = "No SIP Account"
        End If

        If env.StartServer() Then
            env.Send_GetRegStatus(0)

            lbLineStatus.Text = "IDLE"
            btnDial.Text = "Dial"
            btnDial.Enabled = True
            btnHungup.Enabled = False
            btnHold.Enabled = False
            btnTransfer.Enabled = False

            phoneRunning = True

            timer1.Enabled = True

            Return True
        Else
            MessageBox.Show("StartServer Failed! Please make sure the SIP port you set is not being used by another application!")

            lbLineStatus.Text = "ERROR: START PHONE"
            btnDial.Enabled = False
            btnHungup.Enabled = False
            btnHold.Enabled = False
            btnTransfer.Enabled = False

            phoneRunning = False

            timer1.Enabled = False

            Return False
        End If
    End Function

    Public Function FreeSIPServer() As Boolean
        If phoneRunning Then
            timer1.Enabled = False
            phoneRunning = False

            env.StopServer()
            env.DestroyEnv()
            env = Nothing
        End If

        Return True
    End Function


    Private Sub timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles timer1.Tick
        If phoneRunning AndAlso env IsNot Nothing Then
            env.ProcessGTAPIEvent()
        End If
    End Sub

    Private Sub PhoneForm_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
        FreeSIPServer()
    End Sub


    Private Sub btnDial_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDial.Click
        MakeCallOut()
    End Sub

    Public Sub MakeCallOut()
        Dim calledNum As String
        Dim userDomain As String
        userDomain = env.CFG_GetValue("gtsrv.sip.reg1.domain", "")

        If btnDial.Text = "Answer" Then
            env.Send_Answer(0)
        Else
            If tbSipAddr.Text.Contains("@") Then
                calledNum = "<sip:" + tbSipAddr.Text & ">"
                env.Send_Make(0, calledNum, "")
            Else
                If tbSipAddr.Text.Contains(".") Then
                    'assume it is ip address or domain
                    calledNum = "<sip:" + tbSipAddr.Text & ">"
                    env.Send_Make(0, calledNum, "")
                Else
                    If userDomain.Length > 0 Then
                        calledNum = "<sip:" + tbSipAddr.Text & "@" & userDomain & ">"
                        env.Send_Make(0, calledNum, "")
                    Else
                        MessageBox.Show("Cannot reach the destionation!")
                    End If
                End If
            End If
        End If
    End Sub

    Public Sub SetAudioRecording(ByVal r As Boolean, ByVal root_folder As String)
        If r Then
            env.CFG_SetValue("gtphone.audio.record.enabled", "1")
            env.CFG_SetValue("gtphone.audio.record.rootdir", root_folder)
        Else
            env.CFG_SetValue("gtphone.audio.record.enabled", "0")
            env.CFG_SetValue("gtphone.audio.record.rootdir", "")
        End If
    End Sub

    Public Sub SetSoundDevices(ByVal play_device As String, ByVal record_device As String)
        env.CFG_SetValue("gtsrv.sip.dxsound.device.playback", play_device)
        env.CFG_SetValue("gtsrv.sip.dxsound.device.capture", record_device)
        env.Send_ResetDXAudio(0)
    End Sub

    Private Sub btnHungup_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHungup.Click
        env.Send_HangUp(0, 0, "")
    End Sub


    Private Sub btnHold_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHold.Click
        Dim chan As GTAPIASM.GTAPIChan
        chan = env.GetChannel(0)
        If chan.ch_status = GTAPIASM.GTAPI_CHANNEL_STATE.CONNECTED OrElse chan.ch_status = GTAPIASM.GTAPI_CHANNEL_STATE.HOLDING Then
            env.Send_Hold(0)
        End If
    End Sub

    Private Sub btnTransfer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTransfer.Click
        Dim dlg As New TransToForm()
        If dlg.ShowDialog() = DialogResult.OK Then
            Dim sAddr As String = dlg.sTransToAddr
            Dim destAddr As String
            If sAddr.Contains("@") Then
                destAddr = "<sip:" & sAddr & ">"
            Else
                Dim myDomain As String = env.CFG_GetValue("gtsrv.sip.reg1.domain", "")
                If myDomain.Length = 0 Then
                    MessageBox.Show("Error: Cannot transfer call to this address")
                    Return
                End If
                destAddr = "<sip:" & sAddr & "@" & myDomain & ">"
            End If

            env.Send_Transfer(0, destAddr)
        End If
    End Sub

    Private Sub PressButton(ByVal s As String)
        Dim chan As GTAPIASM.GTAPIChan

        chan = env.GetChannel(0)
        If chan.ch_status = GTAPIASM.GTAPI_CHANNEL_STATE.CONNECTED Then
            env.Send_PlayDTMFStr(0, s)
        Else
            tbSipAddr.Text = tbSipAddr.Text + s
        End If

        env.PlayNumTone(s(0))
    End Sub


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        PressButton("1")
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        PressButton("2")
    End Sub

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        PressButton("3")
    End Sub

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        PressButton("4")
    End Sub

    Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
        PressButton("5")
    End Sub

    Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click
        PressButton("6")
    End Sub

    Private Sub Button7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button7.Click
        PressButton("7")
    End Sub

    Private Sub Button8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button8.Click
        PressButton("8")
    End Sub

    Private Sub Button9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button9.Click
        PressButton("9")
    End Sub

    Private Sub Button10_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button10.Click
        PressButton("*")
    End Sub

    Private Sub Button11_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button11.Click
        PressButton("0")
    End Sub

    Private Sub Button12_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button12.Click
        PressButton("#")
    End Sub


    Private Sub cbMuteSpeaker_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cbMuteSpeaker.CheckedChanged
        If cbMuteSpeaker.Checked Then
            env.SetSpeakerMuteStatus(1)
        Else
            env.SetSpeakerMuteStatus(0)
        End If
    End Sub

    Private Sub cbMuteMicrophone_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cbMuteMicrophone.CheckedChanged
        If cbMuteMicrophone.Checked Then
            env.SetMicMuteStatus(1)
        Else
            env.SetMicMuteStatus(0)
        End If
    End Sub


    Private Sub btnOptions_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOptions.Click
        Dim cfg As New CfgForm(cfgWrap)
        If cfg.ShowDialog() = DialogResult.OK Then
            If phoneRunning Then
                FreeSIPServer()
            End If

            InitSIPServer()
        Else
        End If
    End Sub

    Private Sub btnSoundDevice_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSoundDevice.Click
        Dim dlg As New SoundDevice()
        dlg.sSpeaker = env.CFG_GetValue("gtsrv.sip.dxsound.device.playback", "")
        dlg.sMic = env.CFG_GetValue("gtsrv.sip.dxsound.device.capture", "")
        If dlg.ShowDialog() = DialogResult.OK Then
            SetSoundDevices(dlg.sSpeaker, dlg.sMic)
        End If
    End Sub


    Private Sub btnRecording_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRecording.Click
        Dim dlg As New DynamicRecordForm()
        dlg.bEnableRecord = env.CFG_GetValue("gtphone.audio.record.enabled", "0") = "1"
        If dlg.bEnableRecord Then
            dlg.sRootFolder = env.CFG_GetValue("gtphone.audio.record.rootdir", "c:" & vbTab & "emp")
        End If

        If dlg.ShowDialog() = DialogResult.OK Then
            SetAudioRecording(dlg.bEnableRecord, dlg.sRootFolder)
        End If
    End Sub
End Class
