How to develop softphone using Visual C++.Net?

This article is a detailed guide about Ozeki Visual C++ softphone example program. After reading through this page you will be fully familiar with all the essential terms concerning Visual C++ softphone development and what you will need for creating your own solution using Ozeki VoIP SIP SDK.

What is Visual C++.Net? How to get started?

Visual C++.Net is a high level programming language that can be used for creating professional VoIP solutions that use the extraordinary background support of Ozeki VoIP SIP SDK. The example program that is introduced in this article shows all the basic concepts about connecting the C++.Net client application and the C# SDK solutions.

The following program was made in Visual Studio 2010. You will need to have that IDE for having the program work properly.

How to develop softphone using Visual C++.Net?

The softphone is initialized by calling the static CreateSoftPhone method of the SoftPhoneFactory class (Code 1). The softphone needs to be subscribed for the incoming call event too. The event handler method is defined later in the class. The connection will need a SIP account to be defined. The new command is used for creating instances of C# classes.

The telephone function also requires a phone line that is initialized with the SIP account and a specified transport type, in this case it is UDP. The phone line also needs to subscribe for the state change event and it needs to be registered to a SIP PBX.

void WindowMain::InitializeSoftphone()
{
	try
	{
	    m_softPhone = SoftPhoneFactory::CreateSoftPhone(SoftPhoneFactory::GetLocalIP(), 5000, 6000);
		m_softPhone->IncomingCall += gcnew EventHandler<VoIPEventArgs<IPhoneCall^>^>(this, &WindowMain::softPhone_IncomingCall);

		auto sipAccount = gcnew SIPAccount(true, "oz875", "oz875", "oz875", "oz875", "192.168.115.103");
		m_phoneLine = m_softPhone->CreatePhoneLine(sipAccount);
		m_phoneLine->RegistrationStateChanged += gcnew EventHandler<RegistrationStateChangedArgs^>(this, &WindowMain::phoneLine_PhoneLineInformation);
		m_softPhone->RegisterPhoneLine(m_phoneLine);
    }
}
Code 1 - The softphone initialization

The phone call uses some MediaHandler objects that need to be initialized. These are basically the audio devices (microphone and speaker), the MediaConnector that connects the proper devices together and the audio sender and receiver object that are responsible for the audio data sending and receiving during the call (Code 2).

void WindowMain::InitMediaHandlers()
{
    m_microphone = Microphone::GetDefaultDevice();
    m_speaker = Speaker::GetDefaultDevice();

    m_connector = gcnew MediaConnector();
    m_mediaSender = gcnew PhoneCallAudioSender();
    m_mediaReceiver = gcnew PhoneCallAudioReceiver();
}
Code 2 - Initializing the media handlers

Setting the incoming call can be made like in the following method shown in Code 3. The main point in this code is that you should not forget to wire up the call for the possible events that can occur. This will be done by calling the WireUpCallEvents() method.

void WindowMain::SetIncomingCall(IPhoneCall ^phoneCall)
{
    if(this->InvokeRequired)
    {
        auto handler = gcnew SetIncomingCallDelegate(this, &WindowMain::SetIncomingCall);
        this->BeginInvoke(handler, phoneCall);
    }
    else
    {
        labelCallStateInfo->Text = "Incoming call";
        labelDialingNumber->Text = String::Format("from {0}", phoneCall->DialInfo);
        m_call = phoneCall;
        m_incomingCall = true;
    }


    WireUpCallEvents();

}
Code 3 - Setting up the call

The call is subscribed for the possible events in the method shown in Code 4. The main events to be handled are the call state change, the call error and the DMFT signal receive.

void WindowMain::WireUpCallEvents()
{
	m_call->CallStateChanged += gcnew EventHandler<CallStateChangedArgs^>(this, &WindowMain::call_CallStateChanged);
	m_call->DtmfReceived += gcnew EventHandler<VoIPEventArgs<DtmfInfo^>>(this, &WindowMain::call_DtmfReceived);
}
Code 4 - Subscription for the call events

The main softphone functionality is implemented in the call state change handler (Code 5). This method defines what to do in case of an established call or when a call is ended etc.

In case of an established call (the call state is InCall) the devices need to be started and connected to the sender and receiver objects, and those needs to be attached to the call.

In the case of a completed call, the devices need to be stopped and all the handlers need to be disconnected and the sender and receiver need to be detached from the call.

void WindowMain::call_CallStateChanged(Object ^sender, CallStateChangedArgs ^e)
{
    if(this->InvokeRequired)
    {
            auto handler = gcnew SetTextDelegate(this, &WindowMain::SetCallStateInfo);
            BeginInvoke(handler, e->State.ToString());
    }
    else
            SetCallStateInfo(e->State.ToString());

    switch (e->State)
    {
        case CallState::InCall:
            m_microphone->Start();
            m_connector->Connect(m_microphone, m_mediaSender);

            m_speaker->Start();
            m_connector->Connect(m_mediaReceiver, m_speaker);

            m_mediaSender->AttachToCall(m_call);
            m_mediaReceiver->AttachToCall(m_call);

            break;

        case CallState::Completed:
            m_microphone->Stop();
            m_connector->Disconnect(m_microphone, m_mediaSender);

            m_speaker->Stop();
            m_connector->Disconnect(m_mediaReceiver, m_speaker);

            m_mediaSender->Detach();
            m_mediaReceiver->Detach();

            WireDownCallEvents();
            m_call = nullptr;
            SetDialingNumber(String::Empty);
        case CallState::Cancelled:
            WireDownCallEvents();
            m_call = nullptr;
            SetDialingNumber(String::Empty);
            break;
    }
}
Code 5 - The main softphone functionality

Related Pages

More information