Commit 09003d17 authored by Alexandre Savard's avatar Alexandre Savard
Browse files

[#3950] Ability to perform an attended transfer

parent e29bde9d
......@@ -1852,12 +1852,17 @@ static void menuitem_response( gchar *string )
sflphone_join_participant (selected_call->_callID, dragged_call->_callID);
}
else if(g_strcmp0(string, SFL_TRANSFER_CALL) == 0) {
/*
if(selected_call->_state == CALL_STATE_HOLD && dragged_call->_state == CALL_STATE_CURRENT) {
g_print("Calltree: Transfering call %s, to %s", selected_call->_peer_number, dragged_call->_peer_number);
selected_call->_trsft_to = g_strdup(dragged_call->_peer_number);
dbus_hang_up (dragged_call);
dbus_transfert (selected_call);
dbus_transfert (c);
dbus_attended_transfer();
}
*/
g_print("Calltree: Transfering call %s, to %s", selected_call->_peer_number, dragged_call->_peer_number);
dbus_attended_transfer(selected_call, dragged_call);
}
else {
g_print("CallTree: Error unknown option selected in menu %s", string);
......
......@@ -132,6 +132,22 @@
</tp:docstring>
</arg>
</method>
<method name="attendedTransfer" tp:name-for-bindings="attendedTransfer">
<tp:docstring>
Perform an attended transfer on two calls
</tp:docstring>
<arg type="s" name="transferID" direction="in">
<tp:docstring>
The callID of the call to be transfered.
</tp:docstring>
</arg>
<arg type="s" name="targetID" direction="in">
<tp:docstring>
The callID of the target call.
</tp:docstring>
</arg>
</method>
<method name="playDTMF" tp:name-for-bindings="playDTMF">
<tp:docstring>
......
......@@ -818,6 +818,22 @@ dbus_transfert (const callable_obj_t * c)
}
}
void
dbus_attended_transfer (const callable_obj_t *transfer, const callable_obj_t *target)
{
DEBUG("DBUS: Attended tramsfer %s to %s", transfer->_callID, target->_callID);
GError *error = NULL;
org_sflphone_SFLphone_CallManager_attended_transfer (callManagerProxy, transfer->_callID,
target->_callID, &error);
if(error) {
ERROR("Failed to call transfer() on CallManager: %s",
error->message);
g_error_free(error);
}
}
void
dbus_accept (const callable_obj_t * c)
{
......
......@@ -81,6 +81,13 @@ void dbus_hang_up (const callable_obj_t * c);
*/
void dbus_transfert (const callable_obj_t * c);
/**
* CallManager - Perform an attended transfer on two calls
* @param The call to be transfered
* @param The target
*/
void dbus_attended_transfer(const callable_obj_t *, const callable_obj_t *);
/**
* CallManager - Accept a call
* @param c The call to accept
......
......@@ -132,13 +132,13 @@ class G722 : public AudioCodec
// Never set packed TRUE when using 64 kbps
decode_s->packed = FALSE;
memset(decode_s->band, 0, sizeof(decode_s->band) * 2);
memset(decode_s->band, 0, sizeof(decode_s->band));
decode_s->band[0].det = 32;
decode_s->band[1].det = 8;
decode_s->in_bits = 0;
memset(decode_s->x, 0, sizeof(int) * 24);
memset(decode_s->x, 0, sizeof(decode_s->x));
decode_s->in_buffer = 0;
decode_s->in_bits = 0;
......
......@@ -132,6 +132,22 @@
</tp:docstring>
</arg>
</method>
<method name="attendedTransfer" tp:name-for-bindings="attendedTransfer">
<tp:docstring>
Perform an attended transfer on two calls
</tp:docstring>
<arg type="s" name="transferID" direction="in">
<tp:docstring>
The callID of the call to be transfered.
</tp:docstring>
</arg>
<arg type="s" name="targetID" direction="in">
<tp:docstring>
The callID of the target call.
</tp:docstring>
</arg>
</method>
<method name="playDTMF" tp:name-for-bindings="playDTMF">
<tp:docstring>
......
......@@ -170,7 +170,12 @@ CallManager::transfert (const std::string& callID, const std::string& to)
Manager::instance().transferCall (callID, to);
}
void
CallManager::attendedTransfer (const std::string& transferID, const std::string& targetID)
{
_debug("CallManager::attended transfer received");
Manager::instance().attendedTransfer(transferID, targetID);
}
void
CallManager::setVolume (const std::string& device, const double& value)
......
......@@ -76,6 +76,7 @@ class CallManager
void hold (const std::string& callID);
void unhold (const std::string& callID);
void transfert (const std::string& callID, const std::string& to);
void attendedTransfer(const std::string& transferID, const std::string& targetID);
std::map< std::string, std::string > getCallDetails (const std::string& callID);
std::vector< std::string > getCallList (void);
std::string getCurrentCallID();
......
......@@ -651,6 +651,13 @@ IAXVoIPLink::transfer (const CallID& id, const std::string& to)
// removeCall(id);
}
bool
IAXVoIPLink::attendedTransfer(const CallID& transferID, const CallID& targetID)
{
// TODO implement attended transfer for IAX
return false;
}
bool
IAXVoIPLink::refuse (const CallID& id)
{
......
......@@ -79,23 +79,23 @@ class IAXVoIPLink : public VoIPLink
* @return true if successful
* false otherwise
*/
bool init (void);
virtual bool init (void);
/**
* Terminate a voip link by clearing the call list
*/
void terminate (void);
virtual void terminate (void);
/**
* Terminate on call
*/
void terminateCall (const CallID& id);
virtual void terminateCall (const CallID& id);
/**
* Send out registration
* @return bool The new registration state (are we registered ?)
*/
int sendRegister (AccountID id);
virtual int sendRegister (AccountID id);
/**
* Destroy registration session
......@@ -104,7 +104,7 @@ class IAXVoIPLink : public VoIPLink
* @return bool true if we're registered upstream
* false otherwise
*/
int sendUnregister (AccountID id);
virtual int sendUnregister (AccountID id);
/**
* Create a new outgoing call
......@@ -112,7 +112,7 @@ class IAXVoIPLink : public VoIPLink
* @param toUrl The address to call
* @return Call* A pointer on the call
*/
Call* newOutgoingCall (const CallID& id, const std::string& toUrl);
virtual Call* newOutgoingCall (const CallID& id, const std::string& toUrl);
/**
* Answer a call
......@@ -120,7 +120,7 @@ class IAXVoIPLink : public VoIPLink
* @return bool true on success
* false otherwise
*/
bool answer (const CallID& id);
virtual bool answer (const CallID& id);
/**
* Hangup a call
......@@ -128,7 +128,7 @@ class IAXVoIPLink : public VoIPLink
* @return bool true on success
* false otherwise
*/
bool hangup (const CallID& id);
virtual bool hangup (const CallID& id);
/**
* Peer Hungup a call
......@@ -136,7 +136,7 @@ class IAXVoIPLink : public VoIPLink
* @return bool true on success
* false otherwise
*/
bool peerHungup (const CallID& id);
virtual bool peerHungup (const CallID& id);
/**
* Cancel a call
......@@ -144,7 +144,7 @@ class IAXVoIPLink : public VoIPLink
* @return bool true on success
* false otherwise
*/
bool cancel (const CallID& id UNUSED) {
virtual bool cancel (const CallID& id UNUSED) {
return false;
}
......@@ -154,7 +154,7 @@ class IAXVoIPLink : public VoIPLink
* @return bool true on success
* false otherwise
*/
bool onhold (const CallID& id);
virtual bool onhold (const CallID& id);
/**
* Put a call off hold
......@@ -162,7 +162,7 @@ class IAXVoIPLink : public VoIPLink
* @return bool true on success
* false otherwise
*/
bool offhold (const CallID& id);
virtual bool offhold (const CallID& id);
/**
* Transfer a call
......@@ -171,7 +171,15 @@ class IAXVoIPLink : public VoIPLink
* @return bool true on success
* false otherwise
*/
bool transfer (const CallID& id, const std::string& to);
virtual bool transfer (const CallID& id, const std::string& to);
/**
* Perform attended transfer
* @param Transfered call ID
* @param Target call ID
* @return true on success
*/
virtual bool attendedTransfer(const CallID& transferID, const CallID& targetID);
/**
* Refuse a call
......@@ -179,7 +187,7 @@ class IAXVoIPLink : public VoIPLink
* @return bool true on success
* false otherwise
*/
bool refuse (const CallID& id);
virtual bool refuse (const CallID& id);
/**
* Send DTMF
......@@ -188,10 +196,10 @@ class IAXVoIPLink : public VoIPLink
* @return bool true on success
* false otherwise
*/
bool carryingDTMFdigits (const CallID& id, char code);
virtual bool carryingDTMFdigits (const CallID& id, char code);
bool sendTextMessage (sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from);
virtual bool sendTextMessage (sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from);
bool isContactPresenceSupported() {
return false;
......@@ -201,7 +209,7 @@ class IAXVoIPLink : public VoIPLink
* Return the codec protocol used for this call
* @param id The call identifier
*/
std::string getCurrentCodecName();
virtual std::string getCurrentCodecName();
public: // iaxvoiplink only
......
......@@ -668,13 +668,10 @@ bool ManagerImpl::offHoldCall (const CallID& call_id)
//THREAD=Main
bool ManagerImpl::transferCall (const CallID& call_id, const std::string& to)
{
AccountID accountid;
bool returnValue;
bool returnValue = false;;
_info ("Manager: Transfer call %s", call_id.c_str());
CallID current_call_id = getCurrentCallId();
// Direct IP to IP call
if (getConfigFromCall (call_id) == Call::IPtoIP) {
returnValue = SIPVoIPLink::instance (AccountNULL)-> transfer (call_id, to);
......@@ -682,7 +679,7 @@ bool ManagerImpl::transferCall (const CallID& call_id, const std::string& to)
// Classic call, attached to an account
else {
accountid = getAccountFromCall (call_id);
AccountID accountid = getAccountFromCall (call_id);
if (accountid == AccountNULL) {
_warn ("Manager: Call doesn't exists");
......@@ -702,7 +699,7 @@ bool ManagerImpl::transferCall (const CallID& call_id, const std::string& to)
void ManagerImpl::transferFailed ()
{
_debug ("UserAgent: Transfer failed");
_debug ("Manager: Transfer failed");
if (_dbus)
_dbus->getCallManager()->transferFailed();
......@@ -711,13 +708,37 @@ void ManagerImpl::transferFailed ()
void ManagerImpl::transferSucceded ()
{
_debug ("UserAgent: Transfer succeded");
_debug ("Manager: Transfer succeded");
if (_dbus)
_dbus->getCallManager()->transferSucceded();
}
bool ManagerImpl::attendedTransfer(const CallID& transferID, const CallID& targetID)
{
bool returnValue = false;
_debug("Manager: Attended transfer");
// Direct IP to IP call
if (getConfigFromCall (transferID) == Call::IPtoIP) {
returnValue = SIPVoIPLink::instance (AccountNULL)-> attendedTransfer(transferID, targetID);
}
else { // Classic call, attached to an account
AccountID accountid = getAccountFromCall (transferID);
if (accountid == AccountNULL) {
_warn ("Manager: Call doesn't exists");
return false;
}
returnValue = getAccountLink (accountid)->attendedTransfer (transferID, targetID);
}
}
//THREAD=Main : Call:Incoming
bool ManagerImpl::refuseCall (const CallID& id)
{
......
......@@ -252,6 +252,13 @@ class ManagerImpl
*/
bool transferCall (const CallID& id, const std::string& to);
/**
* Attended transfer
* @param The call id to be transfered
* @param The target
*/
bool attendedTransfer(const CallID& transferID, const CallID& targetID);
/**
* Notify the client the transfer is successful
*/
......
......@@ -650,8 +650,8 @@ int SIPVoIPLink::sendRegister (AccountID id)
if (status != PJ_SUCCESS) {
_debug ("UserAgent: Unable to register regc.");
_mutexSIP.leaveMutex();
}
return false;
}
pjsip_tpselector *tp;
......@@ -1170,7 +1170,7 @@ SIPVoIPLink::offhold (const CallID& id)
// Get PayloadType for this codec
AudioCodecType pl = (AudioCodecType) sessionMedia->getPayload();
_debug ("------------------------- payload from session media %d", pl);
_debug ("UserAgent: Payload from session media %d", pl);
try {
// Create a new instance for this codec
......@@ -1281,7 +1281,7 @@ SIPVoIPLink::transfer (const CallID& id, const std::string& to)
return true;
}
bool SIPVoIPLink::transferWithReplaces(const CallID& transferId, const CallID& targetId)
bool SIPVoIPLink::attendedTransfer(const CallID& transferId, const CallID& targetId)
{
char str_dest_buf[PJSIP_MAX_URL_SIZE*2];
pj_str_t str_dest;
......@@ -1293,6 +1293,8 @@ bool SIPVoIPLink::transferWithReplaces(const CallID& transferId, const CallID& t
struct pjsip_evsub_user xfer_cb;
pj_status_t status;
_debug("UserAgent: Attended transfer");
str_dest.ptr = NULL;
str_dest.slen = 0;
......@@ -1310,7 +1312,8 @@ bool SIPVoIPLink::transferWithReplaces(const CallID& transferId, const CallID& t
len = pj_ansi_snprintf(str_dest_buf + str_dest.slen,
sizeof(str_dest_buf) - str_dest.slen,
"Replaces=%.*s"
"?"
"Replaces=%.*s"
"%%3Bto-tag%%3D%.*s"
"%%3Bfrom-tag%%3D%.*s>",
(int)target_dlg->call_id->id.slen,
......@@ -1322,26 +1325,6 @@ bool SIPVoIPLink::transferWithReplaces(const CallID& transferId, const CallID& t
str_dest.ptr = str_dest_buf;
str_dest.slen += len;
/*
len = pj_ansi_snprintf(str_dest_buf + str_dest.slen,
sizeof(str_dest_buf) - str_dest.slen,
"?%s"
"Replaces=%.*s"
"%%3Bto-tag%%3D%.*s"
"%%3Bfrom-tag%%3D%.*s>",
((options&PJSUA_XFER_NO_REQUIRE_REPLACES) ?
"" : "Require=replaces&"),
(int)dest_dlg->call_id->id.slen,
dest_dlg->call_id->id.ptr,
(int)dest_dlg->remote.info->tag.slen,
dest_dlg->remote.info->tag.ptr,
(int)dest_dlg->local.info->tag.slen,
dest_dlg->local.info->tag.ptr);
pjsip_replaces_hdr *replaces_hdr = pjsip_replaces_hdr_create (_pool);
// replaces_hdr;
pjsip_msg_add_hdr (tdata->msg, pjsip_hdr *hdr);
*/
SIPCall *transferCall = getSIPCall (transferId);
......@@ -1397,8 +1380,6 @@ bool SIPVoIPLink::transferStep2 (SIPCall* call)
// TODO is this the best way to proceed?
Manager::instance().peerHungupCall (call->getCallId());
return true;
}
......
......@@ -111,31 +111,31 @@ class SIPVoIPLink : public VoIPLink
* Try to initiate the pjsip engine/thread and set config
* @return bool True if OK
*/
bool init (void);
virtual bool init (void);
/**
* Shut the library and clean up
*/
void terminate (void);
virtual void terminate (void);
/**
* Event listener. Each event send by the call manager is received and handled from here
*/
void getEvent (void);
virtual void getEvent (void);
/**
* Build and send SIP registration request
* @return bool True on success
* false otherwise
*/
int sendRegister (AccountID id);
virtual int sendRegister (AccountID id);
/**
* Build and send SIP unregistration request
* @return bool True on success
* false otherwise
*/
int sendUnregister (AccountID id);
virtual int sendUnregister (AccountID id);
/**
* Place a new call
......@@ -150,42 +150,42 @@ class SIPVoIPLink : public VoIPLink
* @param id The call identifier
* @return int True on success
*/
bool answer (const CallID& id);
virtual bool answer (const CallID& id);
/**
* Hang up the call
* @param id The call identifier
* @return bool True on success
*/
bool hangup (const CallID& id);
virtual bool hangup (const CallID& id);
/**
* Hang up the call
* @param id The call identifier
* @return bool True on success
*/
bool peerHungup (const CallID& id);
virtual bool peerHungup (const CallID& id);
/**
* Cancel the call
* @param id The call identifier
* @return bool True on success
*/
bool cancel (const CallID& id);
virtual bool cancel (const CallID& id);
/**
* Put the call on hold
* @param id The call identifier
* @return bool True on success
*/
bool onhold (const CallID& id);
virtual bool onhold (const CallID& id);
/**
* Put the call off hold
* @param id The call identifier
* @return bool True on success
*/
bool offhold (const CallID& id);
virtual bool offhold (const CallID& id);
/**
* Transfer the call
......@@ -193,11 +193,19 @@ class SIPVoIPLink : public VoIPLink
* @param to The recipient of the transfer
* @return bool True on success
*/
bool transfer (const CallID& id, const std::string& to);
virtual bool transfer (const CallID& id, const std::string& to);
bool transferWithReplaces(const CallID&, const CallID&);
/**
* Attended transfer
* @param The transfered call id
* @param The target call id
* @return True on success
*/
virtual bool attendedTransfer(const CallID&, const CallID&);
/** Handle the incoming refer msg, not finished yet */
/**
* Handle the incoming refer msg, not finished yet
*/
bool transferStep2 (SIPCall* call);
/**
......@@ -205,7 +213,7 @@ class SIPVoIPLink : public VoIPLink
* @param id The call identifier
* @return bool True on success
*/
bool refuse (const CallID& id);
virtual bool refuse (const CallID& id);
/**
* Send DTMF refering to account configuration
......@@ -213,7 +221,7 @@ class SIPVoIPLink : public VoIPLink
* @param code The char code
* @return bool True on success
*/
bool carryingDTMFdigits (const CallID& id, char code);
virtual bool carryingDTMFdigits (const CallID& id, char code);
/**
* Send Dtmf using SIP INFO message
......
......@@ -163,6 +163,14 @@ class VoIPLink
*/
virtual bool transfer (const CallID& id, const std::string& to) = 0;
/**
* Attended transfer
* @param The transfered call id
* @param The target call id
* @return True on success
*/
virtual bool attendedTransfer (const CallID&, const CallID&) = 0;
/**
* Refuse incoming call
* @param id The call identifier
......@@ -178,18 +186,6 @@ class VoIPLink
*/
virtual bool carryingDTMFdigits (const CallID& id, char code) = 0;
/**