# 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:
# 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
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 ... } }
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.
First call getActiveCallItem (opens new window) to get the currently active call object;
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.