Changeset 482 for pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
- Timestamp:
- May 28, 2006 2:58:12 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
r476 r482 85 85 cfg->acc_config[i].reg_timeout = 55; 86 86 } 87 87 88 } 88 89 … … 526 527 int i; 527 528 unsigned options; 528 unsigned clock_rate;529 unsigned samples_per_frame;530 529 pj_str_t codec_id; 531 530 pj_status_t status; … … 604 603 605 604 /* Init options for conference bridge. */ 606 options = 0;605 options = PJMEDIA_CONF_NO_DEVICE; 607 606 608 607 /* Calculate maximum number of ports, if it's not specified */ … … 612 611 613 612 /* Init conference bridge. */ 614 clock_rate = pjsua.config.clock_rate ? pjsua.config.clock_rate : 16000;615 samples_per_frame =clock_rate * 10 / 1000;613 pjsua.clock_rate = pjsua.config.clock_rate ? pjsua.config.clock_rate : 16000; 614 pjsua.samples_per_frame = pjsua.clock_rate * 10 / 1000; 616 615 status = pjmedia_conf_create(pjsua.pool, 617 616 pjsua.config.conf_ports, 618 clock_rate,617 pjsua.clock_rate, 619 618 1, /* mono */ 620 samples_per_frame,619 pjsua.samples_per_frame, 621 620 16, 622 621 options, … … 629 628 } 630 629 630 if (pjsua.config.null_audio == PJ_FALSE) { 631 pjmedia_port *conf_port; 632 633 /* Create sound device port */ 634 status = pjmedia_snd_port_create(pjsua.pool, 635 pjsua.config.snd_capture_id, 636 pjsua.config.snd_player_id, 637 pjsua.clock_rate, 1 /* mono */, 638 pjsua.samples_per_frame, 16, 639 0, &pjsua.snd_port); 640 if (status != PJ_SUCCESS) { 641 pjsua_perror(THIS_FILE, "Unable to create sound device", status); 642 return status; 643 } 644 645 /* Get the port interface of the conference bridge */ 646 conf_port = pjmedia_conf_get_master_port(pjsua.mconf); 647 648 /* Connect conference port interface to sound port */ 649 pjmedia_snd_port_connect( pjsua.snd_port, conf_port); 650 651 } else { 652 pjmedia_port *null_port, *conf_port; 653 654 /* Create NULL port */ 655 status = pjmedia_null_port_create(pjsua.pool, pjsua.clock_rate, 656 1, pjsua.samples_per_frame, 16, 657 &null_port); 658 if (status != PJ_SUCCESS) { 659 pjsua_perror(THIS_FILE, "Unable to create NULL port", status); 660 return status; 661 } 662 663 /* Get the port interface of the conference bridge */ 664 conf_port = pjmedia_conf_get_master_port(pjsua.mconf); 665 666 /* Create master port to control conference bridge's clock */ 667 status = pjmedia_master_port_create(pjsua.pool, null_port, conf_port, 668 0, &pjsua.master_port); 669 if (status != PJ_SUCCESS) { 670 pjsua_perror(THIS_FILE, "Unable to create master port", status); 671 return status; 672 } 673 } 674 631 675 /* Create WAV file player if required: */ 632 676 633 677 if (pjsua.config.wav_file.slen) { 634 pj_str_t port_name; 635 636 /* Create the file player port. */ 637 status = pjmedia_wav_player_port_create( pjsua.pool, 638 pjsua.config.wav_file.ptr, 639 0, 0, -1, NULL, 640 &pjsua.file_port); 678 679 status = pjsua_player_create(&pjsua.config.wav_file, NULL); 641 680 if (status != PJ_SUCCESS) { 642 pjsua_perror(THIS_FILE, 643 "Error playing media file", 681 pjsua_perror(THIS_FILE, "Unable to create file player", 644 682 status); 645 683 return status; 646 684 } 647 648 /* Add port to conference bridge: */649 port_name = pjsua.config.wav_file;650 status = pjmedia_conf_add_port(pjsua.mconf, pjsua.pool,651 pjsua.file_port,652 &port_name,653 &pjsua.wav_slot);654 if (status != PJ_SUCCESS) {655 pjsua_perror(THIS_FILE,656 "Unable to add file player to conference bridge",657 status);658 return status;659 }660 685 } 661 686 662 687 663 688 return PJ_SUCCESS; 689 } 690 691 692 /* 693 * Copy account configuration. 694 */ 695 static void copy_acc_config(pj_pool_t *pool, 696 pjsua_acc_config *dst_acc, 697 const pjsua_acc_config *src_acc) 698 { 699 unsigned j; 700 701 pj_strdup_with_null(pool, &dst_acc->id, &src_acc->id); 702 pj_strdup_with_null(pool, &dst_acc->reg_uri, &src_acc->reg_uri); 703 pj_strdup_with_null(pool, &dst_acc->contact, &src_acc->contact); 704 pj_strdup_with_null(pool, &dst_acc->proxy, &src_acc->proxy); 705 706 for (j=0; j<src_acc->cred_count; ++j) { 707 pj_strdup_with_null(pool, &dst_acc->cred_info[j].realm, 708 &src_acc->cred_info[j].realm); 709 pj_strdup_with_null(pool, &dst_acc->cred_info[j].scheme, 710 &src_acc->cred_info[j].scheme); 711 pj_strdup_with_null(pool, &dst_acc->cred_info[j].username, 712 &src_acc->cred_info[j].username); 713 pj_strdup_with_null(pool, &dst_acc->cred_info[j].data, 714 &src_acc->cred_info[j].data); 715 } 664 716 } 665 717 … … 692 744 pjsua_acc_config *dst_acc = &dst->acc_config[i]; 693 745 const pjsua_acc_config *src_acc = &src->acc_config[i]; 694 unsigned j; 695 696 pj_strdup_with_null(pool, &dst_acc->id, &src_acc->id); 697 pj_strdup_with_null(pool, &dst_acc->reg_uri, &src_acc->reg_uri); 698 pj_strdup_with_null(pool, &dst_acc->contact, &src_acc->contact); 699 pj_strdup_with_null(pool, &dst_acc->proxy, &src_acc->proxy); 700 701 for (j=0; j<src_acc->cred_count; ++j) { 702 pj_strdup_with_null(pool, &dst_acc->cred_info[j].realm, 703 &src_acc->cred_info[j].realm); 704 pj_strdup_with_null(pool, &dst_acc->cred_info[j].scheme, 705 &src_acc->cred_info[j].scheme); 706 pj_strdup_with_null(pool, &dst_acc->cred_info[j].username, 707 &src_acc->cred_info[j].username); 708 pj_strdup_with_null(pool, &dst_acc->cred_info[j].data, 709 &src_acc->cred_info[j].data); 710 } 746 copy_acc_config(pool, dst_acc, src_acc); 711 747 } 712 748 … … 748 784 } 749 785 786 /* Init buddies array */ 787 for (i=0; i<PJ_ARRAY_SIZE(pjsua.buddies); ++i) { 788 pjsua.buddies[i].index = i; 789 } 790 750 791 /* Copy configuration */ 751 792 copy_config(pjsua.pool, &pjsua.config, cfg); … … 757 798 if (pjsua_test_config(&pjsua.config, errmsg, sizeof(errmsg))) { 758 799 PJ_LOG(1,(THIS_FILE, "Error in configuration: %s", errmsg)); 759 return -1; 800 status = -1; 801 goto on_error; 760 802 } 761 803 … … 774 816 &pjsua.sip_sock_name); 775 817 if (status != PJ_SUCCESS) 776 return status;818 goto on_error; 777 819 778 820 pj_strdup2_with_null(pjsua.pool, &pjsua.config.sip_host, … … 786 828 PJ_LOG(1,(THIS_FILE, 787 829 "Error: sip_host and sip_port must be specified")); 788 return PJ_EINVAL; 830 status = PJ_EINVAL; 831 goto on_error; 789 832 } 790 833 … … 796 839 status = init_media(); 797 840 if (status != PJ_SUCCESS) 798 return status;841 goto on_error; 799 842 800 843 … … 805 848 unsigned j; 806 849 for (j=0; j<i; ++j) { 807 pjmedia_transport_udp_close(pjsua.calls[j].med_tp); 850 if (pjsua.calls[i].med_tp) 851 pjsua.calls[i].med_tp->op->destroy(pjsua.calls[i].med_tp); 808 852 } 809 return status;853 goto on_error; 810 854 } 811 855 status = pjmedia_transport_udp_attach(pjsua.med_endpt, NULL, … … 897 941 898 942 on_error: 899 pj _caching_pool_destroy(&pjsua.cp);943 pjsua_destroy(); 900 944 return status; 901 945 } … … 964 1008 965 1009 1010 /* 1011 * Init account 1012 */ 1013 static pj_status_t init_acc(unsigned acc_index) 1014 { 1015 pjsua_acc_config *acc_cfg = &pjsua.config.acc_config[acc_index]; 1016 pjsua_acc *acc = &pjsua.acc[acc_index]; 1017 pjsip_uri *uri; 1018 pjsip_sip_uri *sip_uri; 1019 1020 /* Need to parse local_uri to get the elements: */ 1021 1022 uri = pjsip_parse_uri(pjsua.pool, acc_cfg->id.ptr, 1023 acc_cfg->id.slen, 0); 1024 if (uri == NULL) { 1025 pjsua_perror(THIS_FILE, "Invalid local URI", 1026 PJSIP_EINVALIDURI); 1027 return PJSIP_EINVALIDURI; 1028 } 1029 1030 /* Local URI MUST be a SIP or SIPS: */ 1031 1032 if (!PJSIP_URI_SCHEME_IS_SIP(uri) && 1033 !PJSIP_URI_SCHEME_IS_SIPS(uri)) 1034 { 1035 pjsua_perror(THIS_FILE, "Invalid local URI", 1036 PJSIP_EINVALIDSCHEME); 1037 return PJSIP_EINVALIDSCHEME; 1038 } 1039 1040 1041 /* Get the SIP URI object: */ 1042 1043 sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(uri); 1044 1045 acc->user_part = sip_uri->user; 1046 acc->host_part = sip_uri->host; 1047 1048 /* Build Contact header */ 1049 1050 if (acc_cfg->contact.slen == 0) { 1051 char contact[128]; 1052 const char *addr; 1053 int port; 1054 int len; 1055 1056 addr = pjsua.config.sip_host.ptr; 1057 port = pjsua.config.sip_port; 1058 1059 /* The local Contact is the username@ip-addr, where 1060 * - username is taken from the local URI, 1061 * - ip-addr in UDP transport's address name (which may have been 1062 * resolved from STUN. 1063 */ 1064 1065 /* Build temporary contact string. */ 1066 1067 if (sip_uri->user.slen) { 1068 1069 /* With the user part. */ 1070 len = pj_ansi_snprintf(contact, sizeof(contact), 1071 "<sip:%.*s@%s:%d>", 1072 (int)sip_uri->user.slen, 1073 sip_uri->user.ptr, 1074 addr, port); 1075 } else { 1076 1077 /* Without user part */ 1078 1079 len = pj_ansi_snprintf(contact, sizeof(contact), 1080 "<sip:%s:%d>", 1081 addr, port); 1082 } 1083 1084 if (len < 1 || len >= sizeof(contact)) { 1085 pjsua_perror(THIS_FILE, "Invalid Contact", PJSIP_EURITOOLONG); 1086 return PJSIP_EURITOOLONG; 1087 } 1088 1089 /* Duplicate Contact uri. */ 1090 1091 pj_strdup2(pjsua.pool, &acc_cfg->contact, contact); 1092 1093 } 1094 1095 1096 /* Build route-set for this account */ 1097 if (pjsua.config.outbound_proxy.slen) { 1098 pj_str_t hname = { "Route", 5}; 1099 pjsip_route_hdr *r; 1100 pj_str_t tmp; 1101 1102 pj_strdup_with_null(pjsua.pool, &tmp, &pjsua.config.outbound_proxy); 1103 r = pjsip_parse_hdr(pjsua.pool, &hname, tmp.ptr, tmp.slen, NULL); 1104 pj_list_push_back(&acc->route_set, r); 1105 } 1106 1107 if (acc_cfg->proxy.slen) { 1108 pj_str_t hname = { "Route", 5}; 1109 pjsip_route_hdr *r; 1110 pj_str_t tmp; 1111 1112 pj_strdup_with_null(pjsua.pool, &tmp, &acc_cfg->proxy); 1113 r = pjsip_parse_hdr(pjsua.pool, &hname, tmp.ptr, tmp.slen, NULL); 1114 pj_list_push_back(&acc->route_set, r); 1115 } 1116 1117 return PJ_SUCCESS; 1118 } 1119 1120 /* 1121 * Add a new account. 1122 */ 1123 PJ_DEF(pj_status_t) pjsua_acc_add( const pjsua_acc_config *cfg, 1124 int *acc_index) 1125 { 1126 pj_status_t status; 1127 1128 PJ_ASSERT_RETURN(pjsua.config.acc_cnt<PJ_ARRAY_SIZE(pjsua.config.acc_config), 1129 PJ_ETOOMANY); 1130 1131 copy_acc_config(pjsua.pool, &pjsua.config.acc_config[pjsua.config.acc_cnt], cfg); 1132 1133 status = init_acc(pjsua.config.acc_cnt); 1134 if (status != PJ_SUCCESS) { 1135 pjsua_perror(THIS_FILE, "Error adding account", status); 1136 return status; 1137 } 1138 1139 if (acc_index) 1140 *acc_index = pjsua.config.acc_cnt; 1141 1142 pjsua.config.acc_cnt++; 1143 1144 return PJ_SUCCESS; 1145 } 1146 1147 966 1148 967 1149 /* … … 972 1154 { 973 1155 int i; /* Must be signed */ 1156 unsigned count; 974 1157 pj_status_t status = PJ_SUCCESS; 975 1158 … … 995 1178 pjsua_perror(THIS_FILE, "Unable to start UDP transport", 996 1179 status); 997 return status; 998 } 999 } 1000 1001 /* The last account is default account to be used when nothing match 1002 * any configured accounts. 1180 goto on_error; 1181 } 1182 } 1183 1184 /* Initialize all unused accounts with default id and contact. 1003 1185 */ 1004 1186 { 1005 1187 char buf[80]; 1006 pj_str_t tmp; 1007 pjsua_acc_config *acc_cfg = 1008 &pjsua.config.acc_config[pjsua.config.acc_cnt]; 1188 pj_str_t tmp, id; 1009 1189 1010 1190 tmp.ptr = buf; … … 1012 1192 pjsua.config.sip_host.ptr, 1013 1193 pjsua.config.sip_port); 1014 1015 pj_strdup_with_null( pjsua.pool, &acc_cfg->id, &tmp); 1016 acc_cfg->contact = acc_cfg->id; 1194 pj_strdup_with_null( pjsua.pool, &id, &tmp); 1195 1196 for (i=pjsua.config.acc_cnt; i<PJ_ARRAY_SIZE(pjsua.config.acc_config); 1197 ++i) 1198 { 1199 pjsua_acc_config *acc_cfg = 1200 &pjsua.config.acc_config[pjsua.config.acc_cnt]; 1201 1202 acc_cfg->id = id; 1203 acc_cfg->contact = id; 1204 } 1017 1205 } 1018 1206 … … 1020 1208 /* Initialize accounts: */ 1021 1209 for (i=0; i<(int)pjsua.config.acc_cnt; ++i) { 1022 1023 pjsua_acc_config *acc_cfg = &pjsua.config.acc_config[i]; 1024 pjsua_acc *acc = &pjsua.acc[i]; 1025 pjsip_uri *uri; 1026 pjsip_sip_uri *sip_uri; 1027 1028 /* Need to parse local_uri to get the elements: */ 1029 1030 uri = pjsip_parse_uri(pjsua.pool, acc_cfg->id.ptr, 1031 acc_cfg->id.slen, 0); 1032 if (uri == NULL) { 1033 pjsua_perror(THIS_FILE, "Invalid local URI", 1034 PJSIP_EINVALIDURI); 1035 return PJSIP_EINVALIDURI; 1036 } 1037 1038 /* Local URI MUST be a SIP or SIPS: */ 1039 1040 if (!PJSIP_URI_SCHEME_IS_SIP(uri) && 1041 !PJSIP_URI_SCHEME_IS_SIPS(uri)) 1042 { 1043 pjsua_perror(THIS_FILE, "Invalid local URI", 1044 PJSIP_EINVALIDSCHEME); 1045 return PJSIP_EINVALIDSCHEME; 1046 } 1047 1048 1049 /* Get the SIP URI object: */ 1050 1051 sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(uri); 1052 1053 acc->user_part = sip_uri->user; 1054 acc->host_part = sip_uri->host; 1055 1056 /* Build Contact header */ 1057 1058 if (acc_cfg->contact.slen == 0) { 1059 char contact[128]; 1060 const char *addr; 1061 int port; 1062 int len; 1063 1064 addr = pjsua.config.sip_host.ptr; 1065 port = pjsua.config.sip_port; 1066 1067 /* The local Contact is the username@ip-addr, where 1068 * - username is taken from the local URI, 1069 * - ip-addr in UDP transport's address name (which may have been 1070 * resolved from STUN. 1071 */ 1072 1073 /* Build temporary contact string. */ 1074 1075 if (sip_uri->user.slen) { 1076 1077 /* With the user part. */ 1078 len = pj_ansi_snprintf(contact, sizeof(contact), 1079 "<sip:%.*s@%s:%d>", 1080 (int)sip_uri->user.slen, 1081 sip_uri->user.ptr, 1082 addr, port); 1083 } else { 1084 1085 /* Without user part */ 1086 1087 len = pj_ansi_snprintf(contact, sizeof(contact), 1088 "<sip:%s:%d>", 1089 addr, port); 1090 } 1091 1092 if (len < 1 || len >= sizeof(contact)) { 1093 pjsua_perror(THIS_FILE, "Invalid Contact", PJSIP_EURITOOLONG); 1094 return PJSIP_EURITOOLONG; 1095 } 1096 1097 /* Duplicate Contact uri. */ 1098 1099 pj_strdup2(pjsua.pool, &acc_cfg->contact, contact); 1100 1101 } 1102 1103 1104 /* Build route-set for this account */ 1105 if (pjsua.config.outbound_proxy.slen) { 1106 pj_str_t hname = { "Route", 5}; 1107 pjsip_route_hdr *r; 1108 pj_str_t tmp; 1109 1110 pj_strdup_with_null(pjsua.pool, &tmp, &pjsua.config.outbound_proxy); 1111 r = pjsip_parse_hdr(pjsua.pool, &hname, tmp.ptr, tmp.slen, NULL); 1112 pj_list_push_back(&acc->route_set, r); 1113 } 1114 1115 if (acc_cfg->proxy.slen) { 1116 pj_str_t hname = { "Route", 5}; 1117 pjsip_route_hdr *r; 1118 pj_str_t tmp; 1119 1120 pj_strdup_with_null(pjsua.pool, &tmp, &acc_cfg->proxy); 1121 r = pjsip_parse_hdr(pjsua.pool, &hname, tmp.ptr, tmp.slen, NULL); 1122 pj_list_push_back(&acc->route_set, r); 1123 } 1124 } 1125 1210 status = init_acc(i); 1211 if (status != PJ_SUCCESS) { 1212 pjsua_perror(THIS_FILE, "Error initializing account", status); 1213 goto on_error; 1214 } 1215 } 1126 1216 1127 1217 … … 1138 1228 pj_thread_destroy(pjsua.threads[i]); 1139 1229 } 1140 return status;1230 goto on_error; 1141 1231 } 1142 1232 } … … 1148 1238 status = pjsua_regc_init(i); 1149 1239 if (status != PJ_SUCCESS) 1150 return status;1240 goto on_error; 1151 1241 1152 1242 /* Perform registration, if required. */ 1153 1243 if (pjsua.acc[i].regc) { 1154 pjsua_regc_update(i, 1); 1155 } 1156 } 1157 1158 1159 /* Init buddies */ 1160 for (i=0; i<(int)pjsua.config.buddy_cnt; ++i) { 1161 pjsua.buddies[i].uri = pjsua.config.buddy_uri[i]; 1162 } 1163 pjsua.buddy_cnt = pjsua.config.buddy_cnt; 1164 1165 /* Find account for outgoing preence subscription */ 1166 for (i=0; i<pjsua.buddy_cnt; ++i) { 1167 pjsua.buddies[i].acc_index = 1168 pjsua_find_account_for_outgoing(&pjsua.buddies[i].uri); 1169 } 1244 pjsua_acc_set_registration(i, PJ_TRUE); 1245 } 1246 } 1247 1248 1249 /* Re-init buddies */ 1250 count = pjsua.config.buddy_cnt; 1251 pjsua.config.buddy_cnt = 0; 1252 for (i=0; i<(int)count; ++i) { 1253 pj_str_t uri = pjsua.config.buddy_uri[i]; 1254 pjsua_buddy_add(&uri, NULL); 1255 } 1256 1170 1257 1171 1258 1172 1259 PJ_LOG(3,(THIS_FILE, "PJSUA version %s started", PJ_VERSION)); 1173 1260 return PJ_SUCCESS; 1261 1262 on_error: 1263 pjsua_destroy(); 1264 return status; 1174 1265 } 1175 1266 … … 1190 1281 } 1191 1282 1283 /** 1284 * Get maxinum number of conference ports. 1285 */ 1286 PJ_DEF(unsigned) pjsua_conf_max_ports(void) 1287 { 1288 return pjsua.config.conf_ports; 1289 } 1290 1291 1292 /** 1293 * Enum all conference ports. 1294 */ 1295 PJ_DEF(pj_status_t) pjsua_conf_enum_ports( unsigned *count, 1296 pjmedia_conf_port_info info[]) 1297 { 1298 return pjmedia_conf_get_ports_info(pjsua.mconf, count, info); 1299 } 1300 1301 1302 1303 1304 /** 1305 * Connect conference port. 1306 */ 1307 PJ_DEF(pj_status_t) pjsua_conf_connect( unsigned src_port, 1308 unsigned dst_port) 1309 { 1310 return pjmedia_conf_connect_port(pjsua.mconf, src_port, dst_port, 0); 1311 } 1312 1313 1314 /** 1315 * Connect conference port connection. 1316 */ 1317 PJ_DEF(pj_status_t) pjsua_conf_disconnect( unsigned src_port, 1318 unsigned dst_port) 1319 { 1320 return pjmedia_conf_disconnect_port(pjsua.mconf, src_port, dst_port); 1321 } 1322 1323 1324 1325 /** 1326 * Create a file player. 1327 */ 1328 PJ_DEF(pj_status_t) pjsua_player_create( const pj_str_t *filename, 1329 pjsua_player_id *id) 1330 { 1331 unsigned slot; 1332 char path[128]; 1333 pjmedia_port *port; 1334 pj_status_t status; 1335 1336 if (pjsua.player_cnt >= PJ_ARRAY_SIZE(pjsua.player)) 1337 return PJ_ETOOMANY; 1338 1339 pj_memcpy(path, filename->ptr, filename->slen); 1340 path[filename->slen] = '\0'; 1341 status = pjmedia_wav_player_port_create(pjsua.pool, path, 1342 pjsua.samples_per_frame * 1343 1000 / pjsua.clock_rate, 1344 0, 0, NULL, 1345 &port); 1346 if (status != PJ_SUCCESS) 1347 return status; 1348 1349 status = pjmedia_conf_add_port(pjsua.mconf, pjsua.pool, 1350 port, filename, &slot); 1351 if (status != PJ_SUCCESS) { 1352 pjmedia_port_destroy(port); 1353 return status; 1354 } 1355 1356 pjsua.player[pjsua.player_cnt].port = port; 1357 pjsua.player[pjsua.player_cnt].slot = slot; 1358 1359 if (*id) 1360 *id = pjsua.player_cnt; 1361 1362 ++pjsua.player_cnt; 1363 1364 return PJ_SUCCESS; 1365 } 1366 1367 1368 /** 1369 * Get conference port associated with player. 1370 */ 1371 PJ_DEF(unsigned) pjsua_player_get_conf_port(pjsua_player_id id) 1372 { 1373 PJ_ASSERT_RETURN(id>=0 && id < PJ_ARRAY_SIZE(pjsua.player), PJ_EINVAL); 1374 return pjsua.player[id].slot; 1375 } 1376 1377 1378 /** 1379 * Re-wind playback. 1380 */ 1381 PJ_DEF(pj_status_t) pjsua_player_set_pos(pjsua_player_id id, 1382 pj_uint32_t samples) 1383 { 1384 PJ_ASSERT_RETURN(id>=0 && id < PJ_ARRAY_SIZE(pjsua.player), PJ_EINVAL); 1385 PJ_ASSERT_RETURN(pjsua.player[id].port != NULL, PJ_EINVALIDOP); 1386 1387 return pjmedia_wav_player_port_set_pos(pjsua.player[id].port, samples); 1388 } 1389 1390 1391 /** 1392 * Get conference port associated with player. 1393 */ 1394 PJ_DEF(pj_status_t) pjsua_player_destroy(pjsua_player_id id) 1395 { 1396 PJ_ASSERT_RETURN(id>=0 && id < PJ_ARRAY_SIZE(pjsua.player), PJ_EINVAL); 1397 1398 if (pjsua.player[id].port) { 1399 pjmedia_port_destroy(pjsua.player[id].port); 1400 pjsua.player[id].port = NULL; 1401 pjsua.player[id].slot = 0xFFFF; 1402 pjsua.player_cnt--; 1403 } 1404 1405 return PJ_SUCCESS; 1406 } 1407 1408 1409 /** 1410 * Create a file recorder. 1411 */ 1412 PJ_DEF(pj_status_t) pjsua_recorder_create( const pj_str_t *filename, 1413 pjsua_recorder_id *id) 1414 { 1415 unsigned slot; 1416 char path[128]; 1417 pjmedia_port *port; 1418 pj_status_t status; 1419 1420 if (pjsua.recorder_cnt >= PJ_ARRAY_SIZE(pjsua.recorder)) 1421 return PJ_ETOOMANY; 1422 1423 pj_memcpy(path, filename->ptr, filename->slen); 1424 path[filename->slen] = '\0'; 1425 status = pjmedia_wav_writer_port_create(pjsua.pool, path, 1426 pjsua.clock_rate, 1, 1427 pjsua.samples_per_frame, 1428 16, 0, 0, NULL, 1429 &port); 1430 if (status != PJ_SUCCESS) 1431 return status; 1432 1433 status = pjmedia_conf_add_port(pjsua.mconf, pjsua.pool, 1434 port, filename, &slot); 1435 if (status != PJ_SUCCESS) { 1436 pjmedia_port_destroy(port); 1437 return status; 1438 } 1439 1440 pjsua.recorder[pjsua.recorder_cnt].port = port; 1441 pjsua.recorder[pjsua.recorder_cnt].slot = slot; 1442 1443 if (*id) 1444 *id = pjsua.recorder_cnt; 1445 1446 ++pjsua.recorder_cnt; 1447 1448 return PJ_SUCCESS; 1449 } 1450 1451 1452 /** 1453 * Get conference port associated with recorder. 1454 */ 1455 PJ_DEF(unsigned) pjsua_recorder_get_conf_port(pjsua_recorder_id id) 1456 { 1457 PJ_ASSERT_RETURN(id>=0 && id < PJ_ARRAY_SIZE(pjsua.recorder), PJ_EINVAL); 1458 return pjsua.recorder[id].slot; 1459 } 1460 1461 1462 /** 1463 * Destroy recorder (will complete recording). 1464 */ 1465 PJ_DEF(pj_status_t) pjsua_recorder_destroy(pjsua_recorder_id id) 1466 { 1467 PJ_ASSERT_RETURN(id>=0 && id < PJ_ARRAY_SIZE(pjsua.recorder), PJ_EINVAL); 1468 1469 if (pjsua.recorder[id].port) { 1470 pjmedia_port_destroy(pjsua.recorder[id].port); 1471 pjsua.recorder[id].port = NULL; 1472 pjsua.recorder[id].slot = 0xFFFF; 1473 pjsua.recorder_cnt--; 1474 } 1475 1476 return PJ_SUCCESS; 1477 } 1478 1479 /** 1480 * Enum sound devices. 1481 */ 1482 PJ_DEF(pj_status_t) pjsua_enum_snd_devices( unsigned *count, 1483 pjmedia_snd_dev_info info[]) 1484 { 1485 int i, dev_count; 1486 1487 dev_count = pjmedia_snd_get_dev_count(); 1488 if (dev_count > (int)*count) 1489 dev_count = *count; 1490 1491 for (i=0; i<dev_count; ++i) { 1492 const pjmedia_snd_dev_info *dev_info; 1493 dev_info = pjmedia_snd_get_dev_info(i); 1494 pj_memcpy(&info[i], dev_info, sizeof(pjmedia_snd_dev_info)); 1495 } 1496 1497 *count = dev_count; 1498 return PJ_SUCCESS; 1499 } 1500 1501 1502 /** 1503 * Select or change sound device. 1504 */ 1505 PJ_DEF(pj_status_t) pjsua_set_snd_dev( int snd_capture_id, 1506 int snd_player_id) 1507 { 1508 pjsua.config.snd_capture_id = snd_capture_id; 1509 pjsua.config.snd_player_id = snd_player_id; 1510 return PJ_SUCCESS; 1511 } 1512 1513 1192 1514 /* 1193 1515 * Destroy pjsua. … … 1209 1531 for (i=0; i<(int)pjsua.config.acc_cnt; ++i) { 1210 1532 if (pjsua.acc[i].regc) { 1211 pjsua_ regc_update(i, 0);1533 pjsua_acc_set_registration(i, PJ_FALSE); 1212 1534 } 1213 1535 } … … 1225 1547 1226 1548 /* Wait for some time to allow unregistration to complete: */ 1227 PJ_LOG(4,(THIS_FILE, "Shutting down...")); 1228 busy_sleep(1000); 1229 1230 /* Destroy conference bridge. */ 1231 if (pjsua.mconf) 1232 pjmedia_conf_destroy(pjsua.mconf); 1233 1234 /* Destroy file port */ 1235 if (pjsua.file_port) 1236 pjmedia_port_destroy(pjsua.file_port); 1237 1238 1239 /* Shutdown all codecs: */ 1240 #if PJMEDIA_HAS_SPEEX_CODEC 1241 pjmedia_codec_speex_deinit(); 1242 #endif /* PJMEDIA_HAS_SPEEX_CODEC */ 1243 1244 #if PJMEDIA_HAS_GSM_CODEC 1245 pjmedia_codec_gsm_deinit(); 1246 #endif /* PJMEDIA_HAS_GSM_CODEC */ 1247 1248 #if PJMEDIA_HAS_G711_CODEC 1249 pjmedia_codec_g711_deinit(); 1250 #endif /* PJMEDIA_HAS_G711_CODEC */ 1251 1252 #if PJMEDIA_HAS_L16_CODEC 1253 pjmedia_codec_l16_deinit(); 1254 #endif /* PJMEDIA_HAS_L16_CODEC */ 1549 if (pjsua.endpt) { 1550 PJ_LOG(4,(THIS_FILE, "Shutting down...")); 1551 busy_sleep(1000); 1552 } 1553 1554 /* If we have master port, destroying master port will recursively 1555 * destroy conference bridge, otherwise must destroy it manually. 1556 */ 1557 if (pjsua.master_port) { 1558 pjmedia_master_port_destroy(pjsua.master_port); 1559 pjsua.master_port = NULL; 1560 } else { 1561 if (pjsua.snd_port) { 1562 pjmedia_snd_port_destroy(pjsua.snd_port); 1563 pjsua.snd_port = NULL; 1564 } 1565 if (pjsua.mconf) { 1566 pjmedia_conf_destroy(pjsua.mconf); 1567 pjsua.mconf = NULL; 1568 } 1569 } 1570 1571 /* Destroy file players */ 1572 for (i=0; i<PJ_ARRAY_SIZE(pjsua.player); ++i) { 1573 if (pjsua.player[i].port) { 1574 pjmedia_port_destroy(pjsua.player[i].port); 1575 pjsua.player[i].port = NULL; 1576 } 1577 } 1578 1579 1580 /* Destroy file recorders */ 1581 for (i=0; i<PJ_ARRAY_SIZE(pjsua.recorder); ++i) { 1582 if (pjsua.recorder[i].port) { 1583 pjmedia_port_destroy(pjsua.recorder[i].port); 1584 pjsua.recorder[i].port = NULL; 1585 } 1586 } 1255 1587 1256 1588 1257 1589 /* Close transports */ 1258 for (i=0; pjsua.config.start_rtp_port && i<(int)pjsua.config.max_calls; ++i) { 1259 pjmedia_transport_udp_close(pjsua.calls[i].med_tp); 1590 for (i=0; i<(int)pjsua.config.max_calls; ++i) { 1591 if (pjsua.calls[i].med_tp) { 1592 (*pjsua.calls[i].med_tp->op->destroy)(pjsua.calls[i].med_tp); 1593 pjsua.calls[i].med_tp = NULL; 1594 } 1260 1595 } 1261 1596 1262 1597 /* Destroy media endpoint. */ 1263 1264 pjmedia_endpt_destroy(pjsua.med_endpt); 1598 if (pjsua.med_endpt) { 1599 1600 /* Shutdown all codecs: */ 1601 # if PJMEDIA_HAS_SPEEX_CODEC 1602 pjmedia_codec_speex_deinit(); 1603 # endif /* PJMEDIA_HAS_SPEEX_CODEC */ 1604 1605 # if PJMEDIA_HAS_GSM_CODEC 1606 pjmedia_codec_gsm_deinit(); 1607 # endif /* PJMEDIA_HAS_GSM_CODEC */ 1608 1609 # if PJMEDIA_HAS_G711_CODEC 1610 pjmedia_codec_g711_deinit(); 1611 # endif /* PJMEDIA_HAS_G711_CODEC */ 1612 1613 # if PJMEDIA_HAS_L16_CODEC 1614 pjmedia_codec_l16_deinit(); 1615 # endif /* PJMEDIA_HAS_L16_CODEC */ 1616 1617 1618 pjmedia_endpt_destroy(pjsua.med_endpt); 1619 pjsua.med_endpt = NULL; 1620 } 1265 1621 1266 1622 /* Destroy endpoint. */ 1267 1268 pjsip_endpt_destroy(pjsua.endpt); 1269 pjsua.endpt = NULL; 1623 if (pjsua.endpt) { 1624 pjsip_endpt_destroy(pjsua.endpt); 1625 pjsua.endpt = NULL; 1626 } 1270 1627 1271 1628 /* Destroy caching pool. */ 1272 1273 1629 pj_caching_pool_destroy(&pjsua.cp); 1274 1630 … … 1279 1635 } 1280 1636 1637 1638 /** 1639 * Get SIP endpoint instance. 1640 * Only valid after pjsua_init(). 1641 */ 1642 PJ_DEF(pjsip_endpoint*) pjsua_get_pjsip_endpt(void) 1643 { 1644 return pjsua.endpt; 1645 } 1646 1647 /** 1648 * Get media endpoint instance. 1649 * Only valid after pjsua_init(). 1650 */ 1651 PJ_DEF(pjmedia_endpt*) pjsua_get_pjmedia_endpt(void) 1652 { 1653 return pjsua.med_endpt; 1654 } 1655
Note: See TracChangeset
for help on using the changeset viewer.