diff --git a/sflphone-client-gnome/src/contacts/calltree.c b/sflphone-client-gnome/src/contacts/calltree.c index 129399912a9d2adcd93fe0d1f9cf0f444af42368..8a265047edc46dee3b3051798f01ab5e993bdc5c 100644 --- a/sflphone-client-gnome/src/contacts/calltree.c +++ b/sflphone-client-gnome/src/contacts/calltree.c @@ -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); diff --git a/sflphone-client-gnome/src/dbus/callmanager-introspec.xml b/sflphone-client-gnome/src/dbus/callmanager-introspec.xml index b925e31017b2ccd885e31fc3aed94bdedf1bc869..c17c741fa8113b700266a3eed351c7a553b69015 100644 --- a/sflphone-client-gnome/src/dbus/callmanager-introspec.xml +++ b/sflphone-client-gnome/src/dbus/callmanager-introspec.xml @@ -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> diff --git a/sflphone-client-gnome/src/dbus/dbus.c b/sflphone-client-gnome/src/dbus/dbus.c index 9c01a9d266540a53cf2b99bf5d6e8a8bac73da09..30481d5b876f6cd014eb98a045a1e9e87266b129 100644 --- a/sflphone-client-gnome/src/dbus/dbus.c +++ b/sflphone-client-gnome/src/dbus/dbus.c @@ -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) { diff --git a/sflphone-client-gnome/src/dbus/dbus.h b/sflphone-client-gnome/src/dbus/dbus.h index 423c8ca0a2b4cc563a3b80eccb40918a68c70275..f3245288aeeb15fd41a639e81454b4198e68ec64 100644 --- a/sflphone-client-gnome/src/dbus/dbus.h +++ b/sflphone-client-gnome/src/dbus/dbus.h @@ -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 diff --git a/sflphone-common/src/audio/codecs/g722.cpp b/sflphone-common/src/audio/codecs/g722.cpp index b4b5628306d0fe93d08cb0dc7e9533a5f8829780..3e5c8bf6017b897c2d20671e447f32aaa98c6a9a 100644 --- a/sflphone-common/src/audio/codecs/g722.cpp +++ b/sflphone-common/src/audio/codecs/g722.cpp @@ -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; diff --git a/sflphone-common/src/dbus/callmanager-introspec.xml b/sflphone-common/src/dbus/callmanager-introspec.xml index b925e31017b2ccd885e31fc3aed94bdedf1bc869..d22cbb321d6a391eec41f02125302a3900a2710f 100644 --- a/sflphone-common/src/dbus/callmanager-introspec.xml +++ b/sflphone-common/src/dbus/callmanager-introspec.xml @@ -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> diff --git a/sflphone-common/src/dbus/callmanager.cpp b/sflphone-common/src/dbus/callmanager.cpp index bebccbd49dc8d8b001b566c008be24bb44311451..3d725892de2f780083fdbced9ba485441c421705 100644 --- a/sflphone-common/src/dbus/callmanager.cpp +++ b/sflphone-common/src/dbus/callmanager.cpp @@ -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) diff --git a/sflphone-common/src/dbus/callmanager.h b/sflphone-common/src/dbus/callmanager.h index e741c7dc5a598c16fa459c61afe659861ef3108a..8bea67b486b4094892d1e91054608756e6cfd27b 100644 --- a/sflphone-common/src/dbus/callmanager.h +++ b/sflphone-common/src/dbus/callmanager.h @@ -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(); diff --git a/sflphone-common/src/iax/iaxvoiplink.cpp b/sflphone-common/src/iax/iaxvoiplink.cpp index 3317a56cc7b8f93e83585394e515c63a3993f578..0e09de41e7d636f1907784c11bf0c304f6224250 100644 --- a/sflphone-common/src/iax/iaxvoiplink.cpp +++ b/sflphone-common/src/iax/iaxvoiplink.cpp @@ -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) { diff --git a/sflphone-common/src/iax/iaxvoiplink.h b/sflphone-common/src/iax/iaxvoiplink.h index 82ced25b4da2ce69eca2cfbf1cd7c00bac0a4542..5382a0e81e2140ba5805184c04d5ef7eaeb9fe69 100644 --- a/sflphone-common/src/iax/iaxvoiplink.h +++ b/sflphone-common/src/iax/iaxvoiplink.h @@ -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 diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index 27f75d79eaf4e7dc0c9129c5616a7e427727505d..c2bc5efa177df13a48fc1f5cb848e94d0ef8d629 100644 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -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) { diff --git a/sflphone-common/src/managerimpl.h b/sflphone-common/src/managerimpl.h index 138ed99ccda0c35a7efa012340191036cdd50ca5..c86fc92d98dd792c1a059e53b9f255ca196314cb 100644 --- a/sflphone-common/src/managerimpl.h +++ b/sflphone-common/src/managerimpl.h @@ -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 */ diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp index a75f1efb93744cca0f7e33d5e1d2930c13367e9d..c81658fbb03e0a4dbee9d046c90856f9e4c0bc8e 100644 --- a/sflphone-common/src/sip/sipvoiplink.cpp +++ b/sflphone-common/src/sip/sipvoiplink.cpp @@ -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; } diff --git a/sflphone-common/src/sip/sipvoiplink.h b/sflphone-common/src/sip/sipvoiplink.h index 7dda739419724f8a3d1e89de327d1a752d69576a..c3c22d803c7f2a63e0f860c832a0c40bf185e0ac 100644 --- a/sflphone-common/src/sip/sipvoiplink.h +++ b/sflphone-common/src/sip/sipvoiplink.h @@ -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 diff --git a/sflphone-common/src/voiplink.h b/sflphone-common/src/voiplink.h index 8c55d816604e4dcd718887b3f6304cebb90b9d00..4f09d416516b897bf6dd9aa3d2326d53f6401b0e 100644 --- a/sflphone-common/src/voiplink.h +++ b/sflphone-common/src/voiplink.h @@ -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; - /** - * Set Recording - * @param id The call identifier - */ - // virtual void setRecording(const CallID& id) = 0; - - /** - * Return recording state - * @param id The call identifier - */ - // virtual bool isRecording(const CallID& id) = 0; - /** * Return the codec protocol used for this call * @param id The call identifier