7 呼叫Calls
呼叫由Call类处理
7.1 子类化Call类
要使用Call类,应用程序应创建子类,如:
class MyCall : public Call { public: MyCall(Account &acc, int call_id = PJSUA_INVALID_ID) : Call(acc, call_id) { } ~MyCall() { } // Notification when call‘s state has changed. virtual void onCallState(OnCallStateParam &prm); // Notification when call‘s media state has changed. virtual void onCallMediaState(OnCallMediaStateParam &prm); };
在其子类中,应用程序可以实现呼叫回调,基本上用于处理与呼叫有关的事件,如呼叫状态更改或来电转接请求。
7.2 呼出 Making Outgoing Calls
拨出电话很简单,只需调用Call对象的makeCall()方法即可。假设在“dest_uri”中将Account对象作为acc变量和目标URI字符串,可以使用下面的代码段发起呼出:
Call *call = new MyCall(*acc); CallOpParam prm(true); // Use default call settings try { call->makeCall(dest_uri, prm); } catch(Error& err) { cout << err.info() << endl; }
上面的代码段创建一个Call对象,并使用默认的呼叫设置启动到dest_uri的呼出。对呼叫的后续操作可以使用呼叫实例中的方法,并且将呼叫的事件报告给回调。有关回调的更多内容将稍后解释。
7.3 接收来电 Receiving Incoming Calls
来电将被报告为Account类的onIncomingCall()。必须从Account类派生一个类来处理来电。
以下是回调实现的示例代码:
void MyAccount::onIncomingCall(OnIncomingCallParam &iprm)
{ Call *call = new MyCall(*this, iprm.callId); CallOpParam prm; prm.statusCode = PJSIP_SC_OK; call->answer(prm); }
对于来电,如以上所示,在回调函数中创建呼叫实例。应用程序应确保在呼叫生命周期内存储呼叫实例(直到呼叫断开连接)。
7.4 呼叫属性
所有呼叫属性,如状态,媒体状态,远端(远程对等体)信息等都存储为CallInfo类,可以使用Call的getInfo()方法获取。
7.5 呼叫断开
呼叫断开事件是一个特殊的事件,因为一旦报告此事件的回调返回,该调用将不再有效,并且调用对象的任何操作将引发错误异常。因此,建议删除回调中的调用对象。
Call的onCallState()方法报告呼叫断开,可以检测如下:
void MyCall::onCallState(OnCallStateParam &prm) { CallInfo ci = getInfo(); if (ci.state == PJSIP_INV_STATE_DISCONNECTED) { /* Delete the call */ delete this; } }
7.6 与通话的音频媒体工作
当呼叫的音频媒体准备就绪(或激活)时,只能使用呼叫的音频媒体(例如,连接会议电话中的声音设备的呼叫)。呼叫媒体状态的更改在onCallMediaState()回调中报告,如果呼叫音频媒体已准备就绪(或活动),则Call.getMedia()函数将返回有效的音频媒体。
以下是当媒体处于活动状态时将呼叫连接到声音设备的示例代码:
void MyCall::onCallMediaState(OnCallMediaStateParam &prm) { CallInfo ci = getInfo(); // Iterate all the call medias for (unsigned i = 0; i < ci.media.size(); i++) { if (ci.media[i].type==PJMEDIA_TYPE_AUDIO && getMedia(i)) { AudioMedia *aud_med = (AudioMedia *)getMedia(i); // Connect the call audio media to sound device AudDevManager& mgr = Endpoint::instance().audDevManager(); aud_med->startTransmit(mgr.getPlaybackDevMedia()); mgr.getCaptureDevMedia().startTransmit(*aud_med); } } }
当音频媒体变得不活动时(例如当呼叫被保持)时,不需要停止到/从声音设备的音频媒体传输,因为(当音频媒体不再有效时)呼叫的音频媒体将自动从会议桥被移除,这也将自动删除来自或连接到该呼叫的所有连接。
7.7 呼叫操作
可以调用Call对象的操作,例如挂断,保持呼叫,发送re-INVITE等。请参阅Call的参考文档以获取更多信息。
7.8 即时消息(IM)
可以使用Call.sendInstantMessage()在通话中发送IM。Call.onInstantMessageStatus()回调方法报告传出即时消息的传输状态。
除了发送即时消息,还可以使用Call.sendTypingIndication()发送打字指示。
在呼叫中收到的IM和打字指示将在回调函数Call.onInstantMessage()和Call.onTypingIndication()中报告。
或者,您可以通过使用Buddy.sendInstantMessage()和Buddy.sendTypingIndication()发送IM和打电话外的指示。有关更多信息,请参阅文档。
7.9 类参考
7.9.1 Call
class pj::Call Call.
Public Functions
Call(Account & acc, int call_id = PJSUA_INVALID_ID)