Ozeki VoIP SDK - Product Guide
Developers Guide
Source code explanation for the C# VoIP SIP source implementation of Ozeki VoIP SDK for creating a VB.Net Softphone
![]() |
Download: | Windows_Forms_Softphone_VB_NET.zip (14.9 MB) |
On this page you can find a detailed source code explanation for the C# VoIP SIP source implementation of Ozeki VoIP SDK for creating a VB.Net Softphone.
Graphical User Interface
The GUI of this sample program has been developed with Microsoft Windows Forms
technology. The reason for this is that it allows great flexibility regarding the
appearance of the program.
The main goal of this sample program is to demonstrate the simple and convenient use of
Ozeki SDK (I do not enlist the great functions of WinForms technology in this article).
That is why I created a simple but representative GUI (Figure 1) with basic telephone
functions. The softphone has all the functions that are required for establishing phone
calls effectively like make a call, receive a call, sending and receiving DTMF signals
and display of call events on the interface.

Figure 1 - Ozeki VoIP VB.Net Softphone Sample interface
Running the program
After running the program the telephone automatically registers to the given SIP PBX with the given SIP account. If the registration process is ended successfully we can see Registration succeeded on the display. From this point the softphone is ready to establish and receive calls, to send and receive DTMF signals during calls for navigating in IVR systems. (The source code of the sample program includes settings that depend on the environment so after the download do not forget to customize it. For details please go to Configuration section).
Code
PhoneForm.vb code-behind file belonging to the program interface describes the control events related to the interface and connects the GUI with the logics. The sample program focuses on simplicity and representativeness. The PhoneForm.vb file includes the full logic of the sample program. By opening this PhoneForm.vb file, you can see a few lines of declaration right the beginning that are needed for the use of Ozeki VoIP SIP SDK.
Public Class PhoneForm
' Fields
Private phoneCall As IPhoneCall
Private phoneLine As IPhoneLine
Private phoneLineInformation As PhoneLineState
Private softPhone As ISoftPhone
Private microphone As Microphone = microphone.GetDefaultDevice()
Private speaker As Speaker = speaker.GetDefaultDevice()
Private connector As MediaConnector = New MediaConnector
Private mediaReceiver As PhoneCallAudioReceiver = New PhoneCallAudioReceiver
Private mediaSender As PhoneCallAudioSender = New PhoneCallAudioSender
Private inComingCall As Boolean
ISoftphone:
It represents a telephone, and its telephone line is represented by the
IphoneLine. There can be more telephone lines which means that we can develop a
multi line phone.
Iphoneline:
It represents a telephone line that we can register to a SIP PBX for example,
Asterisk, 3CX, or maybe to other PBXs that are offered by SIP providers.
Registration happens through SIP account.
PhoneLineState:
It is an enum type that represents the status of the telephone line with the
PBX: e.g., registered, not registered, successful/unsuccessful
registration.
IphoneCall:
It represents a call: the status of the call, the direction of the call, on
which telephone line it was created, the called person, etc.
Microphone:
Class for capturing audio data with microphone.
Speaker:
Class for playing audio through speakers.
MediaConnector:
Class for creating connections between 'VoIPMediaHandler' objects.
PhoneCallAudioSender:
It can send audio data to the attached 'IPhoneCall' object.
PhoneCallAudioReceiver:
It can receive audio data from the attached 'IPhoneCall' object.
The softphone is initialized after loading the GUI
By subscribing to the 'Loaded' event of Windows Form windows, it is possible to start the initialization and registration of Ozeki SDK softphone right after 'PhoneMain' window is loaded.
Private Sub InitializeSoftPhone()
Try
Dim ip As IPAddress = SoftPhoneFactory.GetLocalIP()
softPhone = SoftPhoneFactory.CreateSoftPhone(ip, 5700, 5750, 5700, Nothing)
AddHandler softPhone.IncomingCall, New EventHandler(Of VoIPEventArgs(Of IPhoneCall))(AddressOf softPhone_IncommingCall)
phoneLine = softPhone.CreatePhoneLine(New SIPAccount(True, "oz875", "oz875", "oz875", "oz875", "192.168.112.100", 5060), New NatConfiguration(NatTraversalMethod.None))
AddHandler phoneLine.PhoneLineStateChanged, New EventHandler(Of VoIPEventArgs(Of PhoneLineState))(AddressOf phoneLine_PhoneLineInformation)
softPhone.RegisterPhoneLine(phoneLine, Nothing)
Catch ex As Exception
MessageBox.Show("You didn't give your local IP adress, so the program won't run properly.")
End Try
End Sub
Create an instance of the phone via the ’softPhone’ object and give the IP address of your computer and
the port domain that can be used by the phone. Finally specify the port, at which the
SIM messages arriving from the PBX are listened, as the last parameter.
Subscribe to the event that handles incoming calls of the telephone (’softPhone.IncomingCall’)
that occurs when there is an incoming call from the remote end.
Create a phoneLine with a SIP account that can be the user account of your corporate SIP
PBX or a free SIP provider account. To display the status of the created telephone line,
sign up to its ’phoneLine.PhoneLineInformation’ event.
When these things are done you only need to register the created ’phoneLine’ to the
’softPhone’. In this example only one telephone line is registered but of course multiple
telephone line registration is also available.
After these steps you only need to deal with the handling of the calls and to display
them onto the GUI.
Handling the calls
Ozeki SDK represents the incoming and outgoing calls through IpPhoneCall interface. This
interface includes the status of the given call, on which line it was created and who is the
called person. On this object we can pick up or hang up calls. Let’s see the event of the sample program.
a. Outgoing Calls
For establishing an outgoing call, enter the number you wish to dial. Then click the 'Pick Up' button and
the call starts. The surface buttons are assigned to triggers so let's look at the ’Pick Up’
button for details:
Private Sub buttonPickUp_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonPickUp.Click
If inComingCall Then
inComingCall = False
phoneCall.Accept()
ElseIf ((phoneCall Is Nothing) AndAlso Not String.IsNullOrEmpty(labelDialingNumber.Text)) Then
If ((phoneLineInformation <> phoneLineInformation.RegistrationSucceeded) AndAlso (phoneLineInformation <> phoneLineInformation.NoRegNeeded)) Then
MessageBox.Show("Phone line state is not valid!")
Else
phoneCall = Me.softPhone.CreateCallObject(phoneLine, labelDialingNumber.Text)
WireUpCallEvents()
phoneCall.Start()
End If
End If
End Sub
Since you can make and pick up the call with the very same button first you need
to decide if it is an incoming or an outgoing call with the help of a simple bool
variable truth verification (Incoming calls will be detailed later).
Before initiating a phone call, check if the phoneline has successfully registered
to the server when registration is required. If an inappropriate result is
returned the user is informed about the reason of the failure.
If the phoneline is registered, create a IPhoneCall object representing a call
via the ’softPhone.Call’ method and its parameters. The first parameter is the
telephone line on which we would like to initiate calls, the second parameter is
the phone number to be called. In order to make your calls successful, wire up
to some Call Events. Therefore, the audio data arriving from the remote end, the
DTMF signal or changes in call status can be processed effectively. The wire up
process is demonstrated in the sample as follows:
Private Sub WireUpCallEvents() AddHandler phoneCall.CallStateChanged, New EventHandler(Of VoIPEventArgs(Of CallState))(AddressOf phoneCall_CallStateChanged) AddHandler phoneCall.DtmfReceived, New EventHandler(Of VoIPEventArgs(Of DtmfInfo))(AddressOf phoneCall_DtmfReceived) AddHandler phoneCall.CallErrorOccured, New EventHandler(Of VoIPEventArgs(Of CallError))(AddressOf phoneCall_CallErrorOccured) End Sub
CallStateChanged
This event is for displaying the changes in the call status.
MediaDataRecived
The audio data from the remote end arrive via this event.
DtmfReceived
This event is responsible for processing DTMF signals arriving from the remote end.
Via the CallErrorOccured event above you can receive information about the
reasons why the call was not created. For example: the called party is busy,
the call is rejected, the called number does not exist or the called number
is not available.
To wire up to these necessary events you only need to actually start a call.
You can do it with the Start() function of the call object. In this example it is the ’call.Start()’ line.
b. Handling incoming calls
The Ozeki VoIP SIP SDK publishes the incoming calls through the ’ISoftphone’ InComingCall event.
Private Sub softPhone_IncommingCall(ByVal sender As Object, ByVal e As VoIPEventArgs(Of IPhoneCall))
InvokeGUIThread(Sub()
labelCallStateInfo.Text = "Incoming call"
labelDialingNumber.Text = String.Format("from {0}", e.Item.DialInfo)
phoneCall = e.Item
WireUpCallEvents()
inComingCall = True
End Sub)
End Sub
The code sample above is for handling this. It displays incoming calls on the display and registers
onto the necessary events of the object representing incoming calls which was mentioned above.
The incoming call variable notifies the Pick Up button if the call is an outgoing or an incoming one.
c. Ending a call in progress
There are three different ways for ending a call that is in progress.
- We end the call
- The remote end ends the call
- There is a break in network connection
You need to take care of ending the call only if you want to end it. Just like the
’Pick Up’ button the ’Hang Up’ button is also connected to the event manager.
If you use the ’Hang Up’ button the following event manager is responsible for ending the call:
Private Sub buttonHangUp_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonHangUp.Click
If (Not phoneCall Is Nothing) Then
If (phoneCall.CallState = CallState.Ringing AndAlso inComingCall) Then
phoneCall.Reject()
Else
phoneCall.HangUp()
End If
inComingCall = False
phoneCall = Nothing
End If
labelDialingNumber.Text = String.Empty
End Sub
Now it needs to be checked if there is an active call. If there is an active call you need to end it and delete the information related to dialing.
d. Displaying call status
Ozeki VoIP SIP SDK provides the following information about the call status: ringing, InCall, Completed, Rejected, etc.
These call statuses are displayed via the CallStateChange event of ’call’ object. In this
sample program I only focused on the essential options for being simple but demonstrative.
Based on these essential options you can easily create further options.
Private Sub phoneCall_CallStateChanged(ByVal sender As Object, ByVal e As VoIPEventArgs(Of CallState))
InvokeGUIThread(Sub()
labelCallStateInfo.Text = e.Item.ToString
End Sub)
Select Case e.Item
Case CallState.InCall
microphone.Start()
connector.Connect(microphone, mediaSender)
speaker.Start()
connector.Connect(mediaReceiver, speaker)
mediaSender.AttachToCall(phoneCall)
mediaReceiver.AttachToCall(phoneCall)
Return
Case CallState.Completed
microphone.Stop()
connector.Disconnect(microphone, mediaSender)
speaker.Stop()
connector.Disconnect(mediaReceiver, speaker)
mediaSender.Detach()
mediaReceiver.Detach()
WireDownCallEvents()
phoneCall = Nothing
InvokeGUIThread(Sub()
labelDialingNumber.Text = String.Empty
End Sub)
Return
Case CallState.Rejected
Exit Select
Case CallState.Cancelled
WireDownCallEvents()
phoneCall = Nothing
Exit Select
Case Else
Return
End Select
End Sub
The code above is only for reacting to the changes in the call status. For example: If the phone is picked up it starts the voice recording so we can send our audio data to the other party. Moreover it initializes the devices that are necessary for playing incoming audio data.
e. Handling audio data arriving from the remote end
Since we wired up to the MediaDataReceived event of the ’call’ in case of both outgoing and incoming calls,
the incoming PCM audio data only needs to be forwarded to the sound system as it is demonstrated below.
f. Forwarding incoming audio from the microphone to the remote end
via the SDK
The PCM audio data originating from the microphone is forwarded to the ’call’
object that represents the actual call via the process of
SendMediaData. Then audio data is compressed by Ozeki SIP SDK with the right audio codecs and then
sent to the intended person according to the built communication
channel.
g. Receiving DTMF signals
DTMF signals can be received similarly to audio data. Regarding processing, this
sample program only displays the reference value of the received DTMF signal on the
interface.
Private Sub phoneCall_DtmfReceived(ByVal sender As Object, ByVal e As VoIPEventArgs(Of DtmfInfo))
InvokeGUIThread(Sub()
Me.labelCallStateInfo.Text = String.Format("DTMF signal received: {0} ", e.Item.Signal.Signal)
End Sub)
End Sub
h. Sending DTMF signals
DTMF signals can be sent after the call is established for - for example - navigating i
n the IVR menu system of the called call center. Ozeki VoIP SIP SDK allows to send
DTMF signals in a simple way: the ’StartDTMFSignal’ method is called in the object
representing the given call in the following way:
Private Sub buttonKeyPad_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles button9.MouseDown, button8.MouseDown, button7.MouseDown, button6.MouseDown, button5.MouseDown, button4.MouseDown, button3.MouseDown, button2.MouseDown, button12.MouseDown, button11.MouseDown, button10.MouseDown, button1.MouseDown
If ((Not phoneCall Is Nothing) AndAlso (phoneCall.CallState = CallState.InCall)) Then
Dim id As Integer
Dim btn As Button = TryCast(sender, Button)
If (((Not btn Is Nothing) AndAlso (Not btn.Tag Is Nothing)) AndAlso Integer.TryParse(btn.Tag.ToString, id)) Then
phoneCall.StartDTMFSignal(VoIPMediaType.Audio, id)
End If
End If
End Sub
According to RFC2833 the sending of the DTMF signal can represent how long the DTMF signal is being sent. In the sample program I would like to demonstrate this with the events of MouseDown and MouseUP buttons. By using MouseDown, the DTMF signal of the pressed button starts to be sent. By using MouseUP, the sending of the given DTMF signal is ended. The way of ending DTMF signal is similar to the way of start. On the object that represents the current call, the 'StopDTMFSignal' method is called in the following way (where the ID is the number-type DTMF signal according to the reference relating to the pressed button):
phoneCall.StopDTMFSignal(VoIPMediaType.Audio, id)
i. Volume control
Ozeki VoIP SIP SDK provides the possibility for controlling the volume of the microphone and the speaker. You can use a Trackbar element on the GUI for this purpose and set the actual volume according to the track bar value like in the following two functions.
The volume is set every time you change the state of the tracker on the certain Trackbar. This can be implemented easily in the event handler functions for the Trackbar objects (see the following code).
Private Sub MicrophoneVolumeTrackbar_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MicrophoneVolumeTrackbar.Scroll
Dim volume As Single
volume = MicrophoneVolumeTrackbar.Value / 100
microphone.Volume = volume
End Sub
Private Sub SpeakerVolumeTrackbar_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SpeakerVolumeTrackbar.Scroll
Dim volume As Single
volume = SpeakerVolumeTrackbar.Value / 100
speaker.Volume = volume
End Sub
The example program sets the speaker and microphone volume according to the state of the Trackbar trackers using percentage values, but you can also use the actual value of the tracker if you want. In that case you need to delete the "/ 100" section from the code.
Further development possibilities
This sample program is only for handling one telephone line. However, Ozeki VoIP SIP SDK offers the opportunity to develop and handle multiple telephone lines simultaneously. Moreover further functions can also be implemented effectively like call forwarding and chat function. If the above mentioned functions have called your attention contact us at info@voip-sip-sdk.com!
For further information please do not hesitate to contact us at: info@voip-sip-sdk.com!
Pricing and licensing information is available at How to buy page or contact
our sales team at info@voip-sip-sdk.com!
INTERMEDIATE
VoIP technology walkthrough
Softphone development
Webphone development
Mobile development
Voice recording
GETTING AROUND
Sitemap
Search the manual
API documentation
FAQ
Appendix


