diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 1af5fd30fa02ba1517075b503dbd8e29c3f9c493..2edc61879ea206213b10278cb98e40bd15c35002 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -973,6 +973,12 @@ SIPVoIPLink::onhold(const std::string& id) sdpSession->removeAttributeFromLocalAudioMedia("sendonly"); sdpSession->addAttributeToLocalAudioMedia("sendonly"); +#ifdef SFL_VIDEO + sdpSession->removeAttributeFromLocalVideoMedia("sendrecv"); + sdpSession->removeAttributeFromLocalVideoMedia("sendonly"); + sdpSession->addAttributeToLocalVideoMedia("sendonly"); +#endif + SIPSessionReinvite(call); } @@ -1014,6 +1020,12 @@ SIPVoIPLink::offhold(const std::string& id) sdpSession->removeAttributeFromLocalAudioMedia("sendonly"); sdpSession->addAttributeToLocalAudioMedia("sendrecv"); +#ifdef SFL_VIDEO + sdpSession->removeAttributeFromLocalVideoMedia("sendrecv"); + sdpSession->removeAttributeFromLocalVideoMedia("sendonly"); + sdpSession->addAttributeToLocalVideoMedia("sendrecv"); +#endif + if (SIPSessionReinvite(call) == PJ_SUCCESS) call->setState(Call::ACTIVE); } @@ -1173,60 +1185,89 @@ SIPVoIPLink::getCurrentAudioCodecName(Call *call) const return dynamic_cast<SIPCall*>(call)->getLocalSDP()->getAudioCodecName(); } -void -SIPVoIPLink::carryingDTMFdigits(const std::string& id, char code) +/* Only use this macro with string literals or character arrays, will not work + * as expected with char pointers */ +#define CONST_PJ_STR(X) {(char *) (X), ARRAYSIZE(X) - 1} + +namespace { +void sendSIPInfo(const SIPCall &call, const char *const body, const char *const subtype) { - std::string accountID(Manager::instance().getAccountFromCall(id)); - SIPAccount *account = dynamic_cast<SIPAccount*>(Manager::instance().getAccount(accountID)); + pj_str_t methodName = CONST_PJ_STR("INFO"); + pjsip_method method; + pjsip_method_init_np(&method, &methodName); - if (account) { - try { - dtmfSend(getSIPCall(id), code, account->getDtmfType()); - } catch (const VoipLinkException &e) { - // don't do anything if call doesn't exist - } + /* Create request message. */ + pjsip_tx_data *tdata; + + if (pjsip_dlg_create_request(call.inv->dlg, &method, -1, &tdata) != PJ_SUCCESS) { + ERROR("Could not create dialog"); + return; } + + /* Create "application/<subtype>" message body. */ + pj_str_t content; + pj_cstr(&content, body); + const pj_str_t type = CONST_PJ_STR("application"); + pj_str_t pj_subtype; + pj_cstr(&pj_subtype, subtype); + tdata->msg->body = pjsip_msg_body_create(tdata->pool, &type, &pj_subtype, &content); + + if (tdata->msg->body == NULL) + pjsip_tx_data_dec_ref(tdata); + else + pjsip_dlg_send_request(call.inv->dlg, tdata, mod_ua_.id, NULL); +} + +#ifdef SFL_VIDEO +void +requestFastPictureUpdate(const SIPCall &call) +{ + const char * const BODY = + "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + "<media_control><vc_primitive><to_encoder>" + "<picture_fast_update/>" + "</to_encoder></vc_primitive></media_control>"; + + DEBUG("Sending video keyframe request via SIP INFO"); + sendSIPInfo(call, BODY, "media_control+xml"); } +#endif void -SIPVoIPLink::dtmfSend(SIPCall *call, char code, const std::string &dtmf) +dtmfSend(SIPCall &call, char code, const std::string &dtmf) { if (dtmf == SIPAccount::OVERRTP_STR) { - call->getAudioRtp().sendDtmfDigit(code - '0'); + call.getAudioRtp().sendDtmfDigit(code - '0'); return; - } - else if (dtmf != SIPAccount::SIPINFO_STR) { + } else if (dtmf != SIPAccount::SIPINFO_STR) { WARN("SIPVoIPLink: Unknown DTMF type %s, defaulting to %s instead", dtmf.c_str(), SIPAccount::SIPINFO_STR); - } - // else : dtmf == SIPINFO - - pj_str_t methodName = pj_str((char*) "INFO"); - pjsip_method method; - pjsip_method_init_np(&method, &methodName); - - /* Create request message. */ - pjsip_tx_data *tdata; - - if (pjsip_dlg_create_request(call->inv->dlg, &method, -1, &tdata) != PJ_SUCCESS) - return; + } // else : dtmf == SIPINFO int duration = Manager::instance().voipPreferences.getPulseLength(); char dtmf_body[1000]; snprintf(dtmf_body, sizeof dtmf_body - 1, "Signal=%c\r\nDuration=%d\r\n", code, duration); + sendSIPInfo(call, dtmf_body, "dtmf-relay"); +} +} - /* Create "application/dtmf-relay" message body. */ - pj_str_t content = pj_str(dtmf_body); - pj_str_t type = pj_str((char*) "application"); - pj_str_t subtype = pj_str((char*) "dtmf-relay"); - tdata->msg->body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &content); +void +SIPVoIPLink::carryingDTMFdigits(const std::string& id, char code) +{ + std::string accountID(Manager::instance().getAccountFromCall(id)); + SIPAccount *account = dynamic_cast<SIPAccount*>(Manager::instance().getAccount(accountID)); + if (!account) + return; - if (tdata->msg->body == NULL) - pjsip_tx_data_dec_ref(tdata); - else - pjsip_dlg_send_request(call->inv->dlg, tdata, mod_ua_.id, NULL); + try { + SIPCall *call(getSIPCall(id)); + dtmfSend(*call, code, account->getDtmfType()); + } catch (const VoipLinkException &e) { + // don't do anything if call doesn't exist + } } + bool SIPVoIPLink::SIPStartCall(SIPCall *call) { diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h index 8e0ca7d08147baaf59170bc68a92f32a799ac53c..47f1c91dc607ad0635468e6bf4937f8047bfbf4a 100644 --- a/daemon/src/sip/sipvoiplink.h +++ b/daemon/src/sip/sipvoiplink.h @@ -266,8 +266,6 @@ class SIPVoIPLink : public VoIPLink { */ bool SIPStartCall(SIPCall* call); - void dtmfSend(SIPCall *call, char code, const std::string &type); - /** * Threading object */