# Realize One-to-One Voice Calling

This guide introduces how to implement one-to-one voice calling. The API call sequence of one-to-one calls is shown in the figure below:

../../../../_images_en/1-1workflowios.jpg

# Initialize

Extend the JCMediaDeviceCallback (opens new window) object and JCCallCallback (opens new window) object, and implement the pure virtual functions in these two objects:

class JCManager : public JCMediaDeviceCallback, public JCCallCallback
{
public:
    //This callback triggers when the callItem is added
    virtual void onCallItemAdd(JCCallItem* item);
    //This callback triggers when the callItem is removed
    virtual void onCallItemRemove(JCCallItem* item, JCCallReason reason, const char* description);
    //This callback triggers when the callItem‘s status is updated
    virtual void onCallItemUpdate(JCCallItem* item, JCCallItemChangeParam changeParam);
    //This callback triggers when messages are received
    virtual void onMessageReceive(const char* type, const char* content, JCCallItem* item);
    //This callback triggers when get missed calls
    virtual void onMissedCallItem(JCCallItem* item);
    //This callback triggers when the camera is switched
    virtual void onCameraUpdate();

public:
    //JCClient object
    JCMediaDevice* mediaDevice;
    //JCCall object
    JCCall* call;
};

TIP

The object in the callback can only be used in the callback and cannot be saved. The upper layer can obtain the call object through the corresponding method.

Call createJCMediaDevice (opens new window) and createJCCall (opens new window) to initialize the modules needed for one-to-one calling:

bool JCManager::initialize()
{
    //1. Media class
    mediaDevice = createJCMediaDevice(client, this);
    //2. Call class
    call = createJCCall(client, mediaDevice, this);
}

Among them:

  • This in the JCMediaDevice create method is a derived class of JCMediaDeviceCallback (opens new window) , which is used to notify the upper layer of media device-related events. Therefore, you need to create a derived class of JCMediaDeviceCallback, and then implement the pure virtual function of JCMediaDeviceCallback in the derived class.

  • This in the JCCall create method is a derived class of JCCallCallback (opens new window), which is used to notify call-related events to the upper layer. Therefore, you need to create a derived class of JCCallback, and then implement the pure virtual function of JCCallCallback in the derived class.

# Make a call

Call call (opens new window) to initiate a video call, the parameters that need to be filled are:

  • userID Fill in the user ID of the other party.

  • video Select whether to call a video call, and true means to make a video call, while false means to make a voice call.

  • extraParam is a custom pass-through string, which can be obtained through the extraParam property in the JCCallItem object.

// Initiate a voice call
void JCSampleDlg::OnBnClickedButtonVoicecall()
{
    JCManager::shared()->call->call("userID", false, "custom pass-through string");
}

After making a call, both the caller and the called party will receive the callback onCallItemAdd (opens new window) for the new call, and the call state will change to JCCallStatePending. You can implement the onCallItemAdd (opens new window) method in the upper layer and process related logic:

// Receive a new call callback
void JCManager::onCallItemAdd(JCCallItem* item) {
    // Business logic
    if (item->direction == JCCallDirectionIn) {
        // If it is an incoming call
        ...
    } else {
        // If it is an outgoing call
        ...
    }
}

TIP

If the caller wants to cancel the call, he/she can go directly to the hang up part. After calling the hang up interface, the call status becomes the JCCallStateCancel.

# Answer a call

  1. After the caller initiates the call successfully, the called party will receive the onCallItemAdd (opens new window) callback. At this time, the getVideo() method and getDirection() method in the JCCallItem (opens new window) object in the callback can be used to determine whether it is a video call or a voice call. Thus you can deal with it accordingly:

    void JCManager::onCallItemAdd(JCCallItem* item) {
        // 1. If it is an incoming call and is ringing
        if (item->getDirection() == JCCallDirectionIn && item->getState() == JCCallStatePending) {
            // 2. Make corresponding processing, such as "ringing" on the interface
            ...
        }
    }
    
  1. Call answer (opens new window) to answer the call, voice call can only be answered by voice:

    // Get active calls
    JCCallItem* item = JCManager::shared()->call->getActiveCallItem();
    // Answer the call
    JCManager::shared()->call->answer(item, item->getVideo());
    

After the call is answered, the call status changes to JCCallStateConnecting.

TIP

If you want to reject the call at this time, you can go directly to the hang up part. After calling the hang up interface, the call state becomes JCCallStateCanceled.

# Hang up a call

Both the calling party and the called party can hang up the call.

  1. First call getActiveCallItem (opens new window) to get the currently active call object;

  2. After obtaining the current active call object, call term (opens new window) to hang up the current active call:

    void JCSampleDlg::OnBnClickedButtonTermcall()
    {
        // 1. Get the current active call
        JCCallItem* item = JCManager::shared()->call->getActiveCallItem();
        if (item != NULL)
        {
        // 2. Hang up the current active call
        JCManager::shared()->call->term(item, JCCallReasonNone, "term");
        }
    }
    

Now, you have completed the basic fucntion of one-to-one voice calling.