- Timestamp:
- Jul 23, 2018 7:32:54 AM (6 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
r5833 r5834 340 340 } 341 341 342 /*343 * Handler when a transaction within a call has changed state.344 */345 static void on_call_tsx_state(pjsua_call_id call_id,346 pjsip_transaction *tsx,347 pjsip_event *e)348 {349 const pjsip_method info_method =350 {351 PJSIP_OTHER_METHOD,352 { "INFO", 4 }353 };354 355 if (pjsip_method_cmp(&tsx->method, &info_method)==0) {356 /*357 * Handle INFO method.358 */359 const pj_str_t STR_APPLICATION = { "application", 11};360 const pj_str_t STR_DTMF_RELAY = { "dtmf-relay", 10 };361 pjsip_msg_body *body = NULL;362 pj_bool_t dtmf_info = PJ_FALSE;363 364 if (tsx->role == PJSIP_ROLE_UAC) {365 if (e->body.tsx_state.type == PJSIP_EVENT_TX_MSG)366 body = e->body.tsx_state.src.tdata->msg->body;367 else368 body = e->body.tsx_state.tsx->last_tx->msg->body;369 } else {370 if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG)371 body = e->body.tsx_state.src.rdata->msg_info.msg->body;372 }373 374 /* Check DTMF content in the INFO message */375 if (body && body->len &&376 pj_stricmp(&body->content_type.type, &STR_APPLICATION)==0 &&377 pj_stricmp(&body->content_type.subtype, &STR_DTMF_RELAY)==0)378 {379 dtmf_info = PJ_TRUE;380 }381 382 if (dtmf_info && tsx->role == PJSIP_ROLE_UAC &&383 (tsx->state == PJSIP_TSX_STATE_COMPLETED ||384 (tsx->state == PJSIP_TSX_STATE_TERMINATED &&385 e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED)))386 {387 /* Status of outgoing INFO request */388 if (tsx->status_code >= 200 && tsx->status_code < 300) {389 PJ_LOG(4,(THIS_FILE,390 "Call %d: DTMF sent successfully with INFO",391 call_id));392 } else if (tsx->status_code >= 300) {393 PJ_LOG(4,(THIS_FILE,394 "Call %d: Failed to send DTMF with INFO: %d/%.*s",395 call_id,396 tsx->status_code,397 (int)tsx->status_text.slen,398 tsx->status_text.ptr));399 }400 } else if (dtmf_info && tsx->role == PJSIP_ROLE_UAS &&401 tsx->state == PJSIP_TSX_STATE_TRYING)402 {403 /* Answer incoming INFO with 200/OK */404 pjsip_rx_data *rdata;405 pjsip_tx_data *tdata;406 pj_status_t status;407 408 rdata = e->body.tsx_state.src.rdata;409 410 if (rdata->msg_info.msg->body) {411 status = pjsip_endpt_create_response(tsx->endpt, rdata,412 200, NULL, &tdata);413 if (status == PJ_SUCCESS)414 status = pjsip_tsx_send_msg(tsx, tdata);415 416 PJ_LOG(3,(THIS_FILE, "Call %d: incoming INFO:\n%.*s",417 call_id,418 (int)rdata->msg_info.msg->body->len,419 rdata->msg_info.msg->body->data));420 } else {421 status = pjsip_endpt_create_response(tsx->endpt, rdata,422 400, NULL, &tdata);423 if (status == PJ_SUCCESS)424 status = pjsip_tsx_send_msg(tsx, tdata);425 }426 }427 }428 }429 430 342 /* General processing for media state. "mi" is the media index */ 431 343 static void on_call_generic_media_state(pjsua_call_info *ci, unsigned mi, … … 623 535 { 624 536 PJ_LOG(3,(THIS_FILE, "Incoming DTMF on call %d: %c", call_id, dtmf)); 537 } 538 539 static void call_on_dtmf_callback2(pjsua_call_id call_id, 540 const pjsua_dtmf_info *info) 541 { 542 char duration[16]; 543 char method[16]; 544 545 duration[0] = '\0'; 546 547 switch (info->method) { 548 case PJSUA_DTMF_METHOD_RFC2833: 549 pj_ansi_snprintf(method, sizeof(method), "RFC2833"); 550 break; 551 case PJSUA_DTMF_METHOD_SIP_INFO: 552 pj_ansi_snprintf(method, sizeof(method), "SIP INFO"); 553 pj_ansi_snprintf(duration, sizeof(duration), ":duration(%d)", 554 info->duration); 555 break; 556 }; 557 PJ_LOG(3,(THIS_FILE, "Incoming DTMF on call %d: %c%s, using %s method", 558 call_id, info->digit, duration, method)); 625 559 } 626 560 … … 1329 1263 app_config.cfg.cb.on_call_media_state = &on_call_media_state; 1330 1264 app_config.cfg.cb.on_incoming_call = &on_incoming_call; 1331 app_config.cfg.cb.on_call_tsx_state = &on_call_tsx_state; 1332 app_config.cfg.cb.on_dtmf_digit = &call_on_dtmf_callback; 1265 app_config.cfg.cb.on_dtmf_digit2 = &call_on_dtmf_callback2; 1333 1266 app_config.cfg.cb.on_call_redirected = &call_on_redirected; 1334 1267 app_config.cfg.cb.on_reg_state = &on_reg_state; -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app_legacy.c
r5461 r5834 1247 1247 PJ_LOG(3,(THIS_FILE, "No current call")); 1248 1248 } else { 1249 const pj_str_t SIP_INFO = pj_str("INFO");1250 pj_str_t digits;1251 1249 int call = current_call; 1252 int i;1253 1250 pj_status_t status; 1254 1251 char buf[128]; 1252 pjsua_call_send_dtmf_param param; 1255 1253 1256 1254 if (!simple_input("DTMF strings to send (0-9*#A-B)", buf, … … 1263 1261 puts("Call has been disconnected"); 1264 1262 return; 1265 } 1266 1267 digits = pj_str(buf); 1268 for (i=0; i<digits.slen; ++i) { 1269 char body[80]; 1270 pjsua_msg_data msg_data_; 1271 1272 pjsua_msg_data_init(&msg_data_); 1273 msg_data_.content_type = pj_str("application/dtmf-relay"); 1274 1275 pj_ansi_snprintf(body, sizeof(body), 1276 "Signal=%c\r\n" 1277 "Duration=160", 1278 buf[i]); 1279 msg_data_.msg_body = pj_str(body); 1280 1281 status = pjsua_call_send_request(current_call, &SIP_INFO, 1282 &msg_data_); 1283 if (status != PJ_SUCCESS) { 1284 return; 1285 } 1263 } 1264 pjsua_call_send_dtmf_param_default(¶m); 1265 param.digits = pj_str(buf); 1266 param.method = PJSUA_DTMF_METHOD_SIP_INFO; 1267 status = pjsua_call_send_dtmf(current_call, ¶m); 1268 if (status != PJ_SUCCESS) { 1269 pjsua_perror(THIS_FILE, "Error sending DTMF", status); 1286 1270 } 1287 1271 } -
pjproject/trunk/pjsip-apps/src/swig/symbols.i
r5820 r5834 37 37 typedef enum pj_ssl_cert_name_type {PJ_SSL_CERT_NAME_UNKNOWN = 0, PJ_SSL_CERT_NAME_RFC822, PJ_SSL_CERT_NAME_DNS, PJ_SSL_CERT_NAME_URI, PJ_SSL_CERT_NAME_IP} pj_ssl_cert_name_type; 38 38 39 typedef enum pj_ssl_cert_verify_flag_t {PJ_SSL_CERT_ESUCCESS = 0, PJ_SSL_CERT_EISSUER_NOT_FOUND = (1 << 0), PJ_SSL_CERT_EUNTRUSTED = (1 << 1), PJ_SSL_CERT_EVALIDITY_PERIOD = (1 << 2), PJ_SSL_CERT_EINVALID_FORMAT = (1 << 3), PJ_SSL_CERT_EINVALID_PURPOSE = (1 << 4), PJ_SSL_CERT_EISSUER_MISMATCH = (1 << 5), PJ_SSL_CERT_ECRL_FAILURE = (1 << 6), PJ_SSL_CERT_EREVOKED = (1 << 7), PJ_SSL_CERT_ECHAIN_TOO_LONG = (1 << 8), PJ_SSL_CERT_EIDENTITY_NOT_MATCH = (1 << 30), PJ_SSL_CERT_EUNKNOWN = (1 << 31)} pj_ssl_cert_verify_flag_t;39 typedef enum pj_ssl_cert_verify_flag_t {PJ_SSL_CERT_ESUCCESS = 0, PJ_SSL_CERT_EISSUER_NOT_FOUND = 1 << 0, PJ_SSL_CERT_EUNTRUSTED = 1 << 1, PJ_SSL_CERT_EVALIDITY_PERIOD = 1 << 2, PJ_SSL_CERT_EINVALID_FORMAT = 1 << 3, PJ_SSL_CERT_EINVALID_PURPOSE = 1 << 4, PJ_SSL_CERT_EISSUER_MISMATCH = 1 << 5, PJ_SSL_CERT_ECRL_FAILURE = 1 << 6, PJ_SSL_CERT_EREVOKED = 1 << 7, PJ_SSL_CERT_ECHAIN_TOO_LONG = 1 << 8, PJ_SSL_CERT_EIDENTITY_NOT_MATCH = 1 << 30, PJ_SSL_CERT_EUNKNOWN = 1 << 31} pj_ssl_cert_verify_flag_t; 40 40 41 41 typedef enum pj_stun_nat_type {PJ_STUN_NAT_TYPE_UNKNOWN, PJ_STUN_NAT_TYPE_ERR_UNKNOWN, PJ_STUN_NAT_TYPE_OPEN, PJ_STUN_NAT_TYPE_BLOCKED, PJ_STUN_NAT_TYPE_SYMMETRIC_UDP, PJ_STUN_NAT_TYPE_FULL_CONE, PJ_STUN_NAT_TYPE_SYMMETRIC, PJ_STUN_NAT_TYPE_RESTRICTED, PJ_STUN_NAT_TYPE_PORT_RESTRICTED} pj_stun_nat_type; … … 49 49 typedef enum pjmedia_srtp_crypto_option {PJMEDIA_SRTP_NO_ENCRYPTION = 1, PJMEDIA_SRTP_NO_AUTHENTICATION = 2} pjmedia_srtp_crypto_option; 50 50 51 typedef enum pjmedia_srtp_keying_method {PJMEDIA_SRTP_KEYING_SDES = 0, PJMEDIA_SRTP_KEYING_DTLS_SRTP = 1, PJMEDIA_SRTP_KEYINGS_COUNT = 2} pjmedia_srtp_keying_method;51 typedef enum pjmedia_srtp_keying_method {PJMEDIA_SRTP_KEYING_SDES, PJMEDIA_SRTP_KEYING_DTLS_SRTP, PJMEDIA_SRTP_KEYINGS_COUNT} pjmedia_srtp_keying_method; 52 52 53 53 typedef enum pjmedia_vid_stream_rc_method {PJMEDIA_VID_STREAM_RC_NONE = 0, PJMEDIA_VID_STREAM_RC_SIMPLE_BLOCKING = 1} pjmedia_vid_stream_rc_method; … … 180 180 typedef enum pjsua_create_media_transport_flag {PJSUA_MED_TP_CLOSE_MEMBER = 1} pjsua_create_media_transport_flag; 181 181 182 typedef enum pjsua_snd_dev_id {PJSUA_SND_DEFAULT_CAPTURE_DEV = -1, PJSUA_SND_DEFAULT_PLAYBACK_DEV = -2, PJSUA_SND_NO_DEV = -3, PJSUA_SND_NULL_DEV = -99} pjsua_snd_dev_id;182 typedef enum pjsua_snd_dev_id {PJSUA_SND_DEFAULT_CAPTURE_DEV = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV, PJSUA_SND_DEFAULT_PLAYBACK_DEV = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV, PJSUA_SND_NO_DEV = PJMEDIA_AUD_INVALID_DEV, PJSUA_SND_NULL_DEV = -99} pjsua_snd_dev_id; 183 183 184 184 typedef enum pjsua_snd_dev_mode {PJSUA_SND_DEV_SPEAKER_ONLY = 1, PJSUA_SND_DEV_NO_IMMEDIATE_OPEN = 2} pjsua_snd_dev_mode; … … 186 186 typedef enum pjsua_ip_change_op {PJSUA_IP_CHANGE_OP_NULL, PJSUA_IP_CHANGE_OP_RESTART_LIS, PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP, PJSUA_IP_CHANGE_OP_ACC_UPDATE_CONTACT, PJSUA_IP_CHANGE_OP_ACC_HANGUP_CALLS, PJSUA_IP_CHANGE_OP_ACC_REINVITE_CALLS} pjsua_ip_change_op; 187 187 188 typedef enum pjsua_dtmf_method {PJSUA_DTMF_METHOD_RFC2833, PJSUA_DTMF_METHOD_SIP_INFO} pjsua_dtmf_method; 189 -
pjproject/trunk/pjsip-apps/src/swig/symbols.lst
r5820 r5834 35 35 pjsip-ua/sip_inv.h pjsip_inv_state 36 36 37 pjsua-lib/pjsua.h pjsua_invalid_id_const_ pjsua_state pjsua_stun_use pjsua_call_hold_type pjsua_acc_id pjsua_destroy_flag pjsua_100rel_use pjsua_sip_timer_use pjsua_ipv6_use pjsua_nat64_opt pjsua_buddy_status pjsua_call_media_status pjsua_vid_win_id pjsua_call_id pjsua_med_tp_st pjsua_call_vid_strm_op pjsua_vid_req_keyframe_method pjsua_call_flag pjsua_create_media_transport_flag pjsua_snd_dev_id pjsua_snd_dev_mode pjsua_ip_change_op 37 pjsua-lib/pjsua.h pjsua_invalid_id_const_ pjsua_state pjsua_stun_use pjsua_call_hold_type pjsua_acc_id pjsua_destroy_flag pjsua_100rel_use pjsua_sip_timer_use pjsua_ipv6_use pjsua_nat64_opt pjsua_buddy_status pjsua_call_media_status pjsua_vid_win_id pjsua_call_id pjsua_med_tp_st pjsua_call_vid_strm_op pjsua_vid_req_keyframe_method pjsua_call_flag pjsua_create_media_transport_flag pjsua_snd_dev_id pjsua_snd_dev_mode pjsua_ip_change_op pjsua_dtmf_method -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r5828 r5834 800 800 801 801 /** 802 * This enumeration specifies DTMF method. 803 */ 804 typedef enum pjsua_dtmf_method { 805 /** 806 * Send DTMF using RFC2833. 807 */ 808 PJSUA_DTMF_METHOD_RFC2833, 809 810 /** 811 * Send DTMF using SIP INFO. 812 * Notes: 813 * - This method is not finalized in any standard/rfc, however it is 814 * commonly used. 815 * - Warning: in case the remote doesn't support SIP INFO, response might 816 * not be sent and the sender will deal this as timeout and disconnect 817 * the call. 818 */ 819 PJSUA_DTMF_METHOD_SIP_INFO 820 821 } pjsua_dtmf_method; 822 823 824 /** 825 * This will contain the information of the callback \a on_dtmf_digit2. 826 */ 827 typedef struct pjsua_dtmf_info { 828 /** 829 * The method used to send DTMF. 830 */ 831 pjsua_dtmf_method method; 832 833 /** 834 * DTMF ASCII digit 835 */ 836 unsigned digit; 837 838 /** 839 * DTMF signal duration which might be included when sending DTMF using 840 * SIP INFO. 841 */ 842 unsigned duration; 843 844 } pjsua_dtmf_info; 845 846 847 /** 802 848 * Call settings. 803 849 */ … … 961 1007 962 1008 /** 963 * Notify application upon incoming DTMF digits. 1009 * Notify application upon incoming DTMF digits using RFC 2833 payload 1010 * formats. This callback will not be called if app implements \a 1011 * on_dtmf_digit2(). 964 1012 * 965 1013 * @param call_id The call index. … … 967 1015 */ 968 1016 void (*on_dtmf_digit)(pjsua_call_id call_id, int digit); 1017 1018 /** 1019 * Notify application upon incoming DTMF digits using the method specified 1020 * in \a pjsua_dtmf_method. 1021 * 1022 * @param call_id The call index. 1023 * @param info The DTMF info. 1024 */ 1025 void (*on_dtmf_digit2)(pjsua_call_id call_id, const pjsua_dtmf_info *info); 969 1026 970 1027 /** … … 4926 4983 4927 4984 /** 4985 * Specify the default signal duration when sending DTMF using SIP INFO. 4986 * 4987 * Default is 160 4988 */ 4989 #ifndef PJSUA_CALL_SEND_DTMF_DURATION_DEFAULT 4990 # define PJSUA_CALL_SEND_DTMF_DURATION_DEFAULT 160 4991 #endif 4992 4993 4994 /** 4995 * Parameters for sending DTMF. Application should use 4996 * #pjsua_call_send_dtmf_param_default() to initialize this structure 4997 * with its default values. 4998 */ 4999 typedef struct pjsua_call_send_dtmf_param 5000 { 5001 /** 5002 * The method used to send DTMF. 5003 * 5004 * Default: PJSUA_DTMF_METHOD_RFC2833 5005 */ 5006 pjsua_dtmf_method method; 5007 5008 /** 5009 * The signal duration used for the DTMF. 5010 * 5011 * Default: PJSUA_CALL_SEND_DTMF_DURATION_DEFAULT 5012 */ 5013 unsigned duration; 5014 5015 /** 5016 * The DTMF digits to be sent. 5017 */ 5018 pj_str_t digits; 5019 5020 } pjsua_call_send_dtmf_param; 5021 5022 5023 /** 4928 5024 * Initialize call settings. 4929 5025 * … … 4940 5036 PJ_DECL(void) 4941 5037 pjsua_call_vid_strm_op_param_default(pjsua_call_vid_strm_op_param *param); 5038 5039 5040 /** 5041 * Initialize send DTMF param with default values. 5042 * 5043 * @param param The send DTMF param to be initialized. 5044 */ 5045 PJ_DECL(void) 5046 pjsua_call_send_dtmf_param_default(pjsua_call_send_dtmf_param *param); 4942 5047 4943 5048 … … 5408 5513 5409 5514 /** 5410 * Send DTMF digits to remote using RFC 2833 payload formats. 5515 * Send DTMF digits to remote using RFC 2833 payload formats. Use 5516 * #pjsua_call_send_dtmf() to send DTMF using SIP INFO or other method in 5517 * \a pjsua_dtmf_method. App can use \a on_dtmf_digit() or \a on_dtmf_digit2() 5518 * callback to monitor incoming DTMF. 5411 5519 * 5412 5520 * @param call_id Call identification. … … 5420 5528 PJ_DECL(pj_status_t) pjsua_call_dial_dtmf(pjsua_call_id call_id, 5421 5529 const pj_str_t *digits); 5530 5531 /** 5532 * Send DTMF digits to remote. Use this method to send DTMF using the method in 5533 * \a pjsua_dtmf_method. This method will call #pjsua_call_dial_dtmf() when 5534 * sending DTMF using \a PJSUA_DTMF_METHOD_RFC2833. Note that 5535 * \a on_dtmf_digit() callback can only monitor incoming DTMF using RFC 2833. 5536 * App can use \a on_dtmf_digit2() to monitor incoming DTMF using the method in 5537 * \a pjsua_dtmf_method. Note that \a on_dtmf_digit() will not be called once 5538 * \a on_dtmf_digit2() is implemented. 5539 * 5540 * @param call_id Call identification. 5541 * @param param The send DTMF parameter. 5542 * 5543 * @return PJ_SUCCESS on success, or the appropriate error code. 5544 */ 5545 PJ_DECL(pj_status_t) pjsua_call_send_dtmf(pjsua_call_id call_id, 5546 const pjsua_call_send_dtmf_param *param); 5422 5547 5423 5548 /** -
pjproject/trunk/pjsip/include/pjsua2/call.hpp
r5828 r5834 743 743 { 744 744 /** 745 * DTMF sending method. 746 */ 747 pjsua_dtmf_method method; 748 749 /** 745 750 * DTMF ASCII digit. 746 751 */ 747 string digit; 752 string digit; 753 754 /** 755 * DTMF signal duration which might be included when sending DTMF using 756 * SIP INFO. 757 */ 758 unsigned duration; 748 759 }; 749 760 … … 1154 1165 */ 1155 1166 CallVidSetStreamParam(); 1167 }; 1168 1169 /** 1170 * This structure contains parameters for Call::sendDtmf() 1171 */ 1172 struct CallSendDtmfParam 1173 { 1174 /** 1175 * The method used to send DTMF. 1176 * 1177 * Default: PJSUA_DTMF_METHOD_RFC2833 1178 */ 1179 pjsua_dtmf_method method; 1180 1181 /** 1182 * The signal duration used for the DTMF. 1183 * 1184 * Default: PJSUA_CALL_SEND_DTMF_DURATION_DEFAULT 1185 */ 1186 unsigned duration; 1187 1188 /** 1189 * The DTMF digits to be sent. 1190 */ 1191 string digits; 1192 1193 public: 1194 /** 1195 * Default constructor initialize with default value. 1196 */ 1197 CallSendDtmfParam(); 1198 1199 /** 1200 * Convert to pjsip. 1201 */ 1202 pjsua_call_send_dtmf_param toPj() const; 1203 1204 /** 1205 * Convert from pjsip. 1206 */ 1207 void fromPj(const pjsua_call_send_dtmf_param ¶m); 1156 1208 }; 1157 1209 … … 1437 1489 */ 1438 1490 void dialDtmf(const string &digits) throw(Error); 1491 1492 /** 1493 * Send DTMF digits to remote. 1494 * 1495 * @param param The send DTMF parameter. 1496 */ 1497 void sendDtmf(const CallSendDtmfParam ¶m) throw (Error); 1439 1498 1440 1499 /** -
pjproject/trunk/pjsip/include/pjsua2/endpoint.hpp
r5828 r5834 1687 1687 unsigned stream_idx); 1688 1688 static void on_dtmf_digit(pjsua_call_id call_id, int digit); 1689 static void on_dtmf_digit2(pjsua_call_id call_id, 1690 const pjsua_dtmf_info *info); 1689 1691 static void on_call_transfer_request(pjsua_call_id call_id, 1690 1692 const pj_str_t *dst, -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_aud.c
r5825 r5834 557 557 pj_log_push_indent(); 558 558 559 /* For discussions about call mutex protection related to this 560 * callback, please see ticket #460: 561 * http://trac.pjsip.org/repos/ticket/460#comment:4 562 */ 563 if (pjsua_var.ua_cfg.cb.on_dtmf_digit) { 559 if (pjsua_var.ua_cfg.cb.on_dtmf_digit2) { 564 560 pjsua_call_id call_id; 561 pjsua_dtmf_info info; 565 562 566 563 call_id = (pjsua_call_id)(pj_ssize_t)user_data; 567 pjsua_var.ua_cfg.cb.on_dtmf_digit(call_id, digit); 564 info.method = PJSUA_DTMF_METHOD_RFC2833; 565 info.digit = digit; 566 (*pjsua_var.ua_cfg.cb.on_dtmf_digit2)(call_id, &info); 567 } else if (pjsua_var.ua_cfg.cb.on_dtmf_digit) { 568 /* For discussions about call mutex protection related to this 569 * callback, please see ticket #460: 570 * http://trac.pjsip.org/repos/ticket/460#comment:4 571 */ 572 pjsua_call_id call_id; 573 574 call_id = (pjsua_call_id)(pj_ssize_t)user_data; 575 (*pjsua_var.ua_cfg.cb.on_dtmf_digit)(call_id, digit); 568 576 } 569 577 … … 645 653 * callback to the session. 646 654 */ 647 if (pjsua_var.ua_cfg.cb.on_dtmf_digit) { 655 if (pjsua_var.ua_cfg.cb.on_dtmf_digit || 656 pjsua_var.ua_cfg.cb.on_dtmf_digit2) 657 { 648 658 pjmedia_stream_set_dtmf_callback(call_med->strm.a.stream, 649 659 &dtmf_callback, -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r5828 r5834 162 162 } 163 163 164 /* Get DTMF method type name */ 165 static const char* get_dtmf_method_name(int type) 166 { 167 switch (type) { 168 case PJSUA_DTMF_METHOD_RFC2833: 169 return "RFC2833"; 170 case PJSUA_DTMF_METHOD_SIP_INFO: 171 return "SIP INFO"; 172 } 173 return "(Unknown)"; 174 } 164 175 165 176 /* … … 607 618 PJSUA_VID_REQ_KEYFRAME_RTCP_PLI; 608 619 #endif 620 } 621 622 /* 623 * Initialize pjsua_call_send_dtmf_param default values. 624 */ 625 PJ_DEF(void) pjsua_call_send_dtmf_param_default( 626 pjsua_call_send_dtmf_param *param) 627 { 628 pj_bzero(param, sizeof(*param)); 629 param->duration = PJSUA_CALL_SEND_DTMF_DURATION_DEFAULT; 609 630 } 610 631 … … 3133 3154 } 3134 3155 3156 /* 3157 * Send DTMF digits to remote. 3158 */ 3159 PJ_DEF(pj_status_t) pjsua_call_send_dtmf(pjsua_call_id call_id, 3160 const pjsua_call_send_dtmf_param *param) 3161 { 3162 pj_status_t status = PJ_EINVAL; 3163 3164 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls && 3165 param, PJ_EINVAL); 3166 3167 PJ_LOG(4,(THIS_FILE, "Call %d sending DTMF %.*s using %s method", 3168 call_id, (int)param->digits.slen, param->digits.ptr, 3169 get_dtmf_method_name(param->method))); 3170 3171 if (param->method == PJSUA_DTMF_METHOD_RFC2833) { 3172 status = pjsua_call_dial_dtmf(call_id, ¶m->digits); 3173 } else if (param->method == PJSUA_DTMF_METHOD_SIP_INFO) { 3174 const pj_str_t SIP_INFO = pj_str("INFO"); 3175 int i; 3176 3177 for (i = 0; i < param->digits.slen; ++i) { 3178 char body[80]; 3179 pjsua_msg_data msg_data_; 3180 3181 pjsua_msg_data_init(&msg_data_); 3182 msg_data_.content_type = pj_str("application/dtmf-relay"); 3183 3184 pj_ansi_snprintf(body, sizeof(body), 3185 "Signal=%c\r\n" 3186 "Duration=%d", 3187 param->digits.ptr[i], param->duration); 3188 msg_data_.msg_body = pj_str(body); 3189 3190 status = pjsua_call_send_request(call_id, &SIP_INFO, &msg_data_); 3191 } 3192 } 3193 3194 return status; 3195 } 3135 3196 3136 3197 /** … … 5204 5265 const pj_str_t STR_APPLICATION = { "application", 11}; 5205 5266 const pj_str_t STR_MEDIA_CONTROL_XML = { "media_control+xml", 17 }; 5267 /* 5268 * Incoming INFO request for DTMF. 5269 */ 5270 const pj_str_t STR_DTMF_RELAY = { "dtmf-relay", 10 }; 5271 5206 5272 pjsip_rx_data *rdata = e->body.tsx_state.src.rdata; 5207 5273 pjsip_msg_body *body = rdata->msg_info.msg->body; … … 5229 5295 status = pjsip_tsx_send_msg(tsx, tdata); 5230 5296 } 5297 } else if (body && body->len && 5298 pj_stricmp(&body->content_type.type, &STR_APPLICATION)==0 && 5299 pj_stricmp(&body->content_type.subtype, &STR_DTMF_RELAY)==0) 5300 { 5301 pjsip_tx_data *tdata; 5302 pj_status_t status; 5303 pj_bool_t is_handled = PJ_FALSE; 5304 5305 if (pjsua_var.ua_cfg.cb.on_dtmf_digit2) { 5306 pjsua_dtmf_info info; 5307 pj_str_t delim, token, input; 5308 pj_ssize_t found_idx; 5309 5310 delim = pj_str("\r\n"); 5311 input = pj_str(rdata->msg_info.msg->body->data); 5312 found_idx = pj_strtok(&input, &delim, &token, 0); 5313 if (found_idx != input.slen) { 5314 /* Get signal/digit */ 5315 const pj_str_t STR_SIGNAL = { "Signal=", 7 }; 5316 const pj_str_t STR_DURATION = { "Duration=", 9 }; 5317 char *val; 5318 5319 val = pj_strstr(&input, &STR_SIGNAL); 5320 if (val) { 5321 info.digit = *(val+STR_SIGNAL.slen); 5322 is_handled = PJ_TRUE; 5323 5324 /* Get duration */ 5325 input.ptr += token.slen + 2; 5326 input.slen -= (token.slen + 2); 5327 5328 val = pj_strstr(&input, &STR_DURATION); 5329 if (val) { 5330 pj_str_t val_str; 5331 5332 val_str.ptr = val + STR_DURATION.slen; 5333 val_str.slen = input.slen - STR_DURATION.slen; 5334 info.duration = pj_strtoul(&val_str); 5335 } 5336 info.method = PJSUA_DTMF_METHOD_SIP_INFO; 5337 (*pjsua_var.ua_cfg.cb.on_dtmf_digit2)(call->index, 5338 &info); 5339 5340 status = pjsip_endpt_create_response(tsx->endpt, rdata, 5341 200, NULL, &tdata); 5342 if (status == PJ_SUCCESS) 5343 status = pjsip_tsx_send_msg(tsx, tdata); 5344 } 5345 } 5346 } 5347 5348 if (!is_handled) { 5349 status = pjsip_endpt_create_response(tsx->endpt, rdata, 5350 400, NULL, &tdata); 5351 if (status == PJ_SUCCESS) 5352 status = pjsip_tsx_send_msg(tsx, tdata); 5353 } 5354 } 5355 } else if (tsx->role == PJSIP_ROLE_UAC && 5356 pjsip_method_cmp(&tsx->method, &pjsip_info_method)==0 && 5357 (tsx->state == PJSIP_TSX_STATE_COMPLETED || 5358 (tsx->state == PJSIP_TSX_STATE_TERMINATED && 5359 e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED))) 5360 { 5361 const pj_str_t STR_APPLICATION = { "application", 11}; 5362 const pj_str_t STR_DTMF_RELAY = { "dtmf-relay", 10 }; 5363 pjsip_msg_body *body = NULL; 5364 pj_bool_t dtmf_info = PJ_FALSE; 5365 5366 if (e->body.tsx_state.type == PJSIP_EVENT_TX_MSG) 5367 body = e->body.tsx_state.src.tdata->msg->body; 5368 else 5369 body = e->body.tsx_state.tsx->last_tx->msg->body; 5370 5371 /* Check DTMF content in the INFO message */ 5372 if (body && body->len && 5373 pj_stricmp(&body->content_type.type, &STR_APPLICATION)==0 && 5374 pj_stricmp(&body->content_type.subtype, &STR_DTMF_RELAY)==0) 5375 { 5376 dtmf_info = PJ_TRUE; 5377 } 5378 5379 if (dtmf_info && (tsx->state == PJSIP_TSX_STATE_COMPLETED || 5380 (tsx->state == PJSIP_TSX_STATE_TERMINATED && 5381 e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED))) 5382 { 5383 /* Status of outgoing INFO request */ 5384 if (tsx->status_code >= 200 && tsx->status_code < 300) { 5385 PJ_LOG(4,(THIS_FILE, 5386 "Call %d: DTMF sent successfully with INFO", 5387 call->index)); 5388 } else if (tsx->status_code >= 300) { 5389 PJ_LOG(4,(THIS_FILE, 5390 "Call %d: Failed to send DTMF with INFO: %d/%.*s", 5391 call->index, 5392 tsx->status_code, 5393 (int)tsx->status_text.slen, 5394 tsx->status_text.ptr)); 5395 } 5231 5396 } 5232 5397 } -
pjproject/trunk/pjsip/src/pjsua2/call.cpp
r5828 r5834 181 181 this->capDev = prm.cap_dev; 182 182 #endif 183 } 184 185 CallSendDtmfParam::CallSendDtmfParam() 186 { 187 pjsua_call_send_dtmf_param param; 188 pjsua_call_send_dtmf_param_default(¶m); 189 fromPj(param); 190 } 191 192 pjsua_call_send_dtmf_param CallSendDtmfParam::toPj() const 193 { 194 pjsua_call_send_dtmf_param param; 195 pjsua_call_send_dtmf_param_default(¶m); 196 param.method = this->method; 197 param.duration = this->duration; 198 param.digits = str2Pj(this->digits); 199 return param; 200 } 201 202 void CallSendDtmfParam::fromPj(const pjsua_call_send_dtmf_param ¶m) 203 { 204 this->method = param.method; 205 this->duration = param.duration; 206 this->digits = pj2Str(param.digits); 183 207 } 184 208 … … 583 607 } 584 608 609 void Call::sendDtmf(const CallSendDtmfParam ¶m) throw (Error) 610 { 611 pjsua_call_send_dtmf_param pj_param = param.toPj(); 612 613 PJSUA2_CHECK_EXPR(pjsua_call_send_dtmf(id, &pj_param)); 614 } 615 616 585 617 void Call::sendInstantMessage(const SendInstantMessageParam& prm) 586 618 throw(Error) -
pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp
r5828 r5834 1148 1148 char buf[10]; 1149 1149 pj_ansi_sprintf(buf, "%c", digit); 1150 job->prm.digit = (string)buf; 1150 job->prm.digit = string(buf); 1151 1152 Endpoint::instance().utilAddPendingJob(job); 1153 } 1154 1155 void Endpoint::on_dtmf_digit2(pjsua_call_id call_id, 1156 const pjsua_dtmf_info *info) 1157 { 1158 Call *call = Call::lookup(call_id); 1159 if (!call) { 1160 return; 1161 } 1162 1163 PendingOnDtmfDigitCallback *job = new PendingOnDtmfDigitCallback; 1164 job->call_id = call_id; 1165 char buf[10]; 1166 pj_ansi_sprintf(buf, "%c", info->digit); 1167 job->prm.digit = string(buf); 1168 job->prm.method = info->method; 1169 job->prm.duration = info->duration; 1151 1170 1152 1171 Endpoint::instance().utilAddPendingJob(job); … … 1601 1620 ua_cfg.cb.on_stream_created2 = &Endpoint::on_stream_created2; 1602 1621 ua_cfg.cb.on_stream_destroyed = &Endpoint::on_stream_destroyed; 1603 ua_cfg.cb.on_dtmf_digit = &Endpoint::on_dtmf_digit; 1622 //ua_cfg.cb.on_dtmf_digit = &Endpoint::on_dtmf_digit; 1623 ua_cfg.cb.on_dtmf_digit2 = &Endpoint::on_dtmf_digit2; 1604 1624 ua_cfg.cb.on_call_transfer_request2 = &Endpoint::on_call_transfer_request2; 1605 1625 ua_cfg.cb.on_call_transfer_status = &Endpoint::on_call_transfer_status;
Note: See TracChangeset
for help on using the changeset viewer.