Changeset 482
- Timestamp:
- May 28, 2006 2:58:12 PM (19 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip-apps/src/pjsua/main.c
r476 r482 28 28 int main(int argc, char *argv[]) 29 29 { 30 31 30 pjsua_config cfg; 32 31 … … 56 55 * messages. 57 56 */ 58 pjsip_endpt_register_module(pjsua .endpt,57 pjsip_endpt_register_module(pjsua_get_pjsip_endpt(), 59 58 &pjsua_console_app_msg_logger); 60 59 … … 62 61 /* Start pjsua! */ 63 62 if (pjsua_start() != PJ_SUCCESS) { 64 65 63 pjsua_destroy(); 66 64 return 1; … … 79 77 pjsua_destroy(); 80 78 79 /* This is for internal testing, to make sure that pjsua_destroy() 80 * can be called multiple times. 81 */ 82 pjsua_destroy(); 83 81 84 82 85 /* Close logging: */ -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r476 r482 69 69 70 70 71 72 /**73 * Structure to be attached to invite dialog.74 * Given a dialog "dlg", application can retrieve this structure75 * by accessing dlg->mod_data[pjsua.mod.id].76 */77 struct pjsua_call78 {79 unsigned index; /**< Index in pjsua array. */80 pjsip_inv_session *inv; /**< The invite session. */81 pj_time_val start_time;/**< First INVITE sent/received. */82 pj_time_val res_time; /**< First response sent/received. */83 pj_time_val conn_time; /**< Connected/confirmed time. */84 pj_time_val dis_time; /**< Disconnect time. */85 int acc_index; /**< Account index being used. */86 pjmedia_session *session; /**< The media session. */87 unsigned conf_slot; /**< Slot # in conference bridge. */88 pjsip_evsub *xfer_sub; /**< Xfer server subscription, if this89 call was triggered by xfer. */90 pjmedia_sock_info skinfo; /**< Preallocated media sockets. */91 pjmedia_transport *med_tp; /**< Media transport. */92 void *app_data; /**< Application data. */93 pj_timer_entry refresh_tm;/**< Timer to send re-INVITE. */94 pj_timer_entry hangup_tm; /**< Timer to hangup call. */95 };96 97 typedef struct pjsua_call pjsua_call;98 99 100 /**101 * Buddy data.102 */103 struct pjsua_buddy104 {105 pj_str_t uri; /**< Buddy URI */106 int acc_index; /**< Which account to use. */107 pj_bool_t monitor; /**< Should we monitor? */108 pjsip_evsub *sub; /**< Buddy presence subscription */109 pjsip_pres_status status; /**< Buddy presence status. */110 };111 112 typedef struct pjsua_buddy pjsua_buddy;113 114 115 /**116 * Server presence subscription list head.117 */118 struct pjsua_srv_pres119 {120 PJ_DECL_LIST_MEMBER(struct pjsua_srv_pres);121 pjsip_evsub *sub;122 char *remote;123 };124 125 typedef struct pjsua_srv_pres pjsua_srv_pres;126 127 128 71 /** 129 72 * Account configuration. … … 159 102 */ 160 103 typedef struct pjsua_acc_config pjsua_acc_config; 161 162 163 /**164 * Account165 */166 struct pjsua_acc167 {168 int index; /**< Index in accounts array. */169 pj_str_t user_part; /**< User part of local URI. */170 pj_str_t host_part; /**< Host part of local URI. */171 172 pjsip_regc *regc; /**< Client registration session. */173 pj_timer_entry reg_timer; /**< Registration timer. */174 pj_status_t reg_last_err; /**< Last registration error. */175 int reg_last_code; /**< Last status last register. */176 177 pjsip_route_hdr route_set; /**< Route set. */178 179 pj_bool_t online_status; /**< Our online status. */180 pjsua_srv_pres pres_srv_list; /**< Server subscription list. */181 182 void *app_data; /**< Application data. */183 };184 185 186 /**187 * @see pjsua_acc188 */189 typedef struct pjsua_acc pjsua_acc;190 104 191 105 … … 248 162 unsigned stun_port2; 249 163 164 /** Sound player device ID (default: 0) */ 165 unsigned snd_player_id; 166 167 /** Sound capture device ID (default: 0) */ 168 unsigned snd_capture_id; 169 250 170 /** Internal clock rate (to be applied to sound devices and conference 251 171 * bridge, default is 0/follows the codec, or 44100 for MacOS). … … 340 260 { 341 261 /** 342 * Notify UI when invite state has changed. 262 * Notify application when invite state has changed. 263 * Application may then query the call info to get the 264 * detail call states. 343 265 */ 344 266 void (*on_call_state)(int call_index, pjsip_event *e); 345 267 346 268 /** 347 * Notify UI when registration status has changed. 269 * Notify application on call being transfered. 270 * Application can decide to accept/reject transfer request 271 * by setting the code (default is 200). When this callback 272 * is not defined, the default behavior is to accept the 273 * transfer. 274 */ 275 void (*on_call_transfered)(int call_index, 276 const pj_str_t *dst, 277 pjsip_status_code *code); 278 279 /** 280 * Notify application when registration status has changed. 281 * Application may then query the account info to get the 282 * registration details. 348 283 */ 349 284 void (*on_reg_state)(int acc_index); 350 285 351 286 /** 352 * Notify UI on incoming pager (i.e. MESSAGE request). 287 * Notify application when the buddy state has changed. 288 * Application may then query the buddy into to get the details. 289 */ 290 void (*on_buddy_state)(int buddy_index); 291 292 /** 293 * Notify application on incoming pager (i.e. MESSAGE request). 353 294 * Argument call_index will be -1 if MESSAGE request is not related to an 354 295 * existing call. … … 358 299 359 300 /** 360 * Notify UIabout typing indication.301 * Notify application about typing indication. 361 302 */ 362 303 void (*on_typing)(int call_index, const pj_str_t *from, … … 371 312 372 313 373 /* PJSUA application variables. */ 374 struct pjsua 314 /** 315 * Call info. 316 */ 317 struct pjsua_call_info 375 318 { 376 /* Control: */ 377 pj_caching_pool cp; /**< Global pool factory. */ 378 pjsip_endpoint *endpt; /**< Global endpoint. */ 379 pj_pool_t *pool; /**< pjsua's private pool. */ 380 pjsip_module mod; /**< pjsua's PJSIP module. */ 381 382 383 /* Config: */ 384 pjsua_config config; /**< PJSUA configs */ 385 386 /* Application callback: */ 387 pjsua_callback cb; /**< Application callback. */ 388 389 /* Media: */ 390 pjmedia_endpt *med_endpt; /**< Media endpoint. */ 391 pjmedia_conf *mconf; /**< Media conference. */ 392 unsigned wav_slot; /**< WAV player slot in bridge */ 393 pjmedia_port *file_port; /**< WAV player port. */ 394 395 396 /* Account: */ 397 pjsua_acc acc[PJSUA_MAX_ACC]; /** Client regs array. */ 398 399 400 /* Threading (optional): */ 401 pj_thread_t *threads[8]; /**< Thread instances. */ 402 pj_bool_t quit_flag; /**< To signal thread to quit. */ 403 404 /* Transport (UDP): */ 405 pj_sock_t sip_sock; /**< SIP UDP socket. */ 406 pj_sockaddr_in sip_sock_name; /**< Public/STUN UDP socket addr. */ 407 408 409 /* PJSUA Calls: */ 410 int call_cnt; /**< Number of calls. */ 411 pjsua_call calls[PJSUA_MAX_CALLS]; /** Calls array. */ 412 413 414 /* SIMPLE and buddy status: */ 415 int buddy_cnt; 416 pjsua_buddy buddies[PJSUA_MAX_BUDDIES]; 319 unsigned index; 320 pj_bool_t active; 321 pjsip_role_e role; 322 pj_str_t local_info; 323 pj_str_t remote_info; 324 pjsip_inv_state state; 325 pj_str_t state_text; 326 pj_time_val connect_duration; 327 pj_time_val total_duration; 328 pjsip_status_code cause; 329 pj_str_t cause_text; 330 pj_bool_t has_media; 331 unsigned conf_slot; 417 332 }; 418 333 419 420 /** PJSUA instance. */ 421 extern struct pjsua pjsua; 334 typedef struct pjsua_call_info pjsua_call_info; 335 336 337 enum pjsua_buddy_status 338 { 339 PJSUA_BUDDY_STATUS_UNKNOWN, 340 PJSUA_BUDDY_STATUS_ONLINE, 341 PJSUA_BUDDY_STATUS_OFFLINE, 342 }; 343 344 typedef enum pjsua_buddy_status pjsua_buddy_status; 345 346 347 /** 348 * Buddy info. 349 */ 350 struct pjsua_buddy_info 351 { 352 unsigned index; 353 pj_bool_t is_valid; 354 pj_str_t name; 355 pj_str_t display_name; 356 pj_str_t host; 357 unsigned port; 358 pj_str_t uri; 359 pjsua_buddy_status status; 360 pj_str_t status_text; 361 pj_bool_t monitor; 362 }; 363 364 typedef struct pjsua_buddy_info pjsua_buddy_info; 365 366 367 /** 368 * Account info. 369 */ 370 struct pjsua_acc_info 371 { 372 unsigned index; 373 pj_str_t acc_id; 374 pj_bool_t has_registration; 375 int expires; 376 pjsip_status_code status; 377 pj_str_t status_text; 378 pj_bool_t online_status; 379 char buf[PJ_ERR_MSG_SIZE]; 380 }; 381 382 typedef struct pjsua_acc_info pjsua_acc_info; 383 384 385 typedef int pjsua_player_id; 386 typedef int pjsua_recorder_id; 422 387 423 388 … … 434 399 435 400 /** 436 * Testconfiguration.401 * Validate configuration. 437 402 */ 438 403 PJ_DECL(pj_status_t) pjsua_test_config(const pjsua_config *cfg, … … 442 407 443 408 /** 444 * Create pjsua application. 445 * This initializes pjlib/pjlib-util, and creates memory pool factory to 446 * be used by application. 409 * Instantiate pjsua application. This initializes pjlib/pjlib-util, and 410 * creates memory pool factory to be used by application. 447 411 */ 448 412 PJ_DECL(pj_status_t) pjsua_create(void); … … 470 434 PJ_DECL(pj_status_t) pjsua_start(void); 471 435 472 473 436 /** 474 437 * Destroy pjsua. 475 438 */ 476 439 PJ_DECL(pj_status_t) pjsua_destroy(void); 440 441 /** 442 * Get SIP endpoint instance. 443 * Only valid after pjsua_init(). 444 */ 445 PJ_DECL(pjsip_endpoint*) pjsua_get_pjsip_endpt(void); 446 447 /** 448 * Get media endpoint instance. 449 * Only valid after pjsua_init(). 450 */ 451 PJ_DECL(pjmedia_endpt*) pjsua_get_pjmedia_endpt(void); 452 453 /** 454 * Replace media transport. 455 */ 456 PJ_DECL(pj_status_t) pjsua_set_call_media_transport(unsigned call_index, 457 const pjmedia_sock_info *i, 458 pjmedia_transport *tp); 477 459 478 460 … … 482 464 483 465 /** 466 * Get maximum number of calls configured in pjsua. 467 */ 468 PJ_DECL(unsigned) pjsua_get_max_calls(void); 469 470 /** 471 * Get current number of active calls. 472 */ 473 PJ_DECL(unsigned) pjsua_get_call_count(void); 474 475 /** 476 * Check if the specified call has active INVITE session and the INVITE 477 * session has not been disconnected. 478 */ 479 PJ_DECL(pj_bool_t) pjsua_call_is_active(unsigned call_index); 480 481 482 /** 483 * Check if call has a media session. 484 */ 485 PJ_DECL(pj_bool_t) pjsua_call_has_media(unsigned call_index); 486 487 488 /** 489 * Get call info. 490 */ 491 PJ_DECL(pj_status_t) pjsua_get_call_info(unsigned call_index, 492 pjsua_call_info *info); 493 494 495 /** 496 * Duplicate call info. 497 */ 498 PJ_DECL(void) pjsua_dup_call_info(pj_pool_t *pool, 499 pjsua_call_info *dst_info, 500 const pjsua_call_info *src_info); 501 502 503 /** 484 504 * Make outgoing call. 485 505 */ 486 PJ_DECL(pj_status_t) pjsua_make_call( intacc_index,487 const char *cstr_dest_uri,506 PJ_DECL(pj_status_t) pjsua_make_call(unsigned acc_index, 507 const pj_str_t *dst_uri, 488 508 int *p_call_index); 489 509 … … 515 535 * Transfer call. 516 536 */ 517 PJ_DECL(void) pjsua_call_xfer(int call_index, const char *dest); 537 PJ_DECL(void) pjsua_call_xfer(unsigned call_index, const pj_str_t *dest); 538 539 /** 540 * Dial DTMF. 541 */ 542 PJ_DECL(pj_status_t) pjsua_call_dial_dtmf(unsigned call_index, 543 const pj_str_t *digits); 518 544 519 545 … … 521 547 * Send instant messaging inside INVITE session. 522 548 */ 523 PJ_DECL(void) pjsua_call_send_im(int call_index, const char*text);549 PJ_DECL(void) pjsua_call_send_im(int call_index, const pj_str_t *text); 524 550 525 551 … … 536 562 537 563 /***************************************************************************** 538 * PJSUA Client Registration API (defined in pjsua_reg.c). 539 */ 564 * PJSUA Account and Client Registration API (defined in pjsua_reg.c). 565 */ 566 567 568 /** 569 * Get number of accounts. 570 */ 571 PJ_DECL(unsigned) pjsua_get_acc_count(void); 572 573 /** 574 * Get account info. 575 */ 576 PJ_DECL(pj_status_t) pjsua_acc_get_info(unsigned acc_index, 577 pjsua_acc_info *info); 578 579 /** 580 * Add a new account. 581 * This function should be called after pjsua_init(). 582 * Application should call pjsua_acc_set_registration() to start 583 * registration for this account. 584 */ 585 PJ_DECL(pj_status_t) pjsua_acc_add(const pjsua_acc_config *cfg, 586 int *acc_index); 587 588 589 /** 590 * Set account's presence status. 591 * Must call pjsua_pres_refresh() after this. 592 */ 593 PJ_DECL(pj_status_t) pjsua_acc_set_online_status(unsigned acc_index, 594 pj_bool_t is_online); 595 540 596 541 597 /** … … 543 599 * this will start unregistration process. 544 600 */ 545 PJ_DECL(void) pjsua_ regc_update(intacc_index, pj_bool_t renew);601 PJ_DECL(void) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew); 546 602 547 603 … … 553 609 554 610 /** 611 * Get buddy count. 612 */ 613 PJ_DECL(unsigned) pjsua_get_buddy_count(void); 614 615 616 /** 617 * Get buddy info. 618 */ 619 PJ_DECL(pj_status_t) pjsua_buddy_get_info(unsigned buddy_index, 620 pjsua_buddy_info *info); 621 622 /** 623 * Add new buddy. 624 */ 625 PJ_DECL(pj_status_t) pjsua_buddy_add(const pj_str_t *uri, 626 int *buddy_index); 627 628 629 /** 630 * Enable/disable buddy's presence monitoring. 631 * Must call pjsua_pres_refresh() after this. 632 */ 633 PJ_DECL(pj_status_t) pjsua_buddy_subscribe_pres(unsigned buddy_index, 634 pj_bool_t monitor); 635 636 637 /** 555 638 * Refresh both presence client and server subscriptions. 556 639 */ … … 577 660 * Send IM outside dialog. 578 661 */ 579 PJ_DECL(pj_status_t) pjsua_im_send(int acc_index, const char*dst_uri,580 const char*text);662 PJ_DECL(pj_status_t) pjsua_im_send(int acc_index, const pj_str_t *dst_uri, 663 const pj_str_t *text); 581 664 582 665 … … 584 667 * Send typing indication outside dialog. 585 668 */ 586 PJ_DECL(pj_status_t) pjsua_im_typing(int acc_index, const char*dst_uri,669 PJ_DECL(pj_status_t) pjsua_im_typing(int acc_index, const pj_str_t *dst_uri, 587 670 pj_bool_t is_typing); 588 671 672 673 674 /***************************************************************************** 675 * Media. 676 */ 677 678 /** 679 * Get maxinum number of conference ports. 680 */ 681 PJ_DECL(unsigned) pjsua_conf_max_ports(void); 682 683 684 /** 685 * Enum all conference ports. 686 */ 687 PJ_DECL(pj_status_t) pjsua_conf_enum_ports(unsigned *count, 688 pjmedia_conf_port_info info[]); 689 690 691 /** 692 * Connect conference port. 693 */ 694 PJ_DECL(pj_status_t) pjsua_conf_connect(unsigned src_port, 695 unsigned dst_port); 696 697 698 /** 699 * Connect conference port connection. 700 */ 701 PJ_DECL(pj_status_t) pjsua_conf_disconnect(unsigned src_port, 702 unsigned dst_port); 703 704 705 /** 706 * Create a file player. 707 */ 708 PJ_DECL(pj_status_t) pjsua_player_create(const pj_str_t *filename, 709 pjsua_player_id *id); 710 711 712 /** 713 * Get conference port associated with player. 714 */ 715 PJ_DECL(unsigned) pjsua_player_get_conf_port(pjsua_player_id id); 716 717 718 /** 719 * Set playback position. 720 */ 721 PJ_DECL(pj_status_t) pjsua_player_set_pos(pjsua_player_id id, 722 pj_uint32_t samples); 723 724 725 /** 726 * Destroy player. 727 */ 728 PJ_DECL(pj_status_t) pjsua_player_destroy(pjsua_player_id id); 729 730 731 732 /** 733 * Create a file recorder. 734 */ 735 PJ_DECL(pj_status_t) pjsua_recorder_create(const pj_str_t *filename, 736 pjsua_recorder_id *id); 737 738 739 /** 740 * Get conference port associated with recorder. 741 */ 742 PJ_DECL(unsigned) pjsua_recorder_get_conf_port(pjsua_recorder_id id); 743 744 745 /** 746 * Destroy recorder (will complete recording). 747 */ 748 PJ_DECL(pj_status_t) pjsua_recorder_destroy(pjsua_recorder_id id); 749 750 751 /** 752 * Enum sound devices. 753 */ 754 PJ_DECL(pj_status_t) pjsua_enum_snd_devices(unsigned *count, 755 pjmedia_snd_dev_info info[]); 756 757 758 /** 759 * Select or change sound device. 760 * This will only change the device ID in configuration (not changing 761 * the current device). 762 */ 763 PJ_DECL(pj_status_t) pjsua_set_snd_dev(int snd_capture_id, 764 int snd_player_id); 589 765 590 766 … … 610 786 611 787 /** 788 * Get pjsua running config. 789 */ 790 PJ_DECL(const pjsua_config*) pjsua_get_config(void); 791 792 793 /** 612 794 * Dump settings. 795 * If cfg is NULL, it will dump current settings. 613 796 */ 614 797 PJ_DECL(int) pjsua_dump_settings(const pjsua_config *cfg, -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r476 r482 126 126 127 127 /** 128 * Get maximum number of calls configured in pjsua. 129 */ 130 PJ_DEF(unsigned) pjsua_get_max_calls(void) 131 { 132 return pjsua.config.max_calls; 133 } 134 135 136 /** 137 * Get current number of active calls. 138 */ 139 PJ_DEF(unsigned) pjsua_get_call_count(void) 140 { 141 return pjsua.call_cnt; 142 } 143 144 145 /** 146 * Check if the specified call is active. 147 */ 148 PJ_DEF(pj_bool_t) pjsua_call_is_active(unsigned call_index) 149 { 150 PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, 151 PJ_EINVAL); 152 return pjsua.calls[call_index].inv != NULL && 153 pjsua.calls[call_index].inv->state != PJSIP_INV_STATE_DISCONNECTED; 154 } 155 156 /** 157 * Check if call has a media session. 158 */ 159 PJ_DEF(pj_bool_t) pjsua_call_has_media(unsigned call_index) 160 { 161 PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, PJ_EINVAL); 162 return pjsua.calls[call_index].session != NULL; 163 } 164 165 166 /** 167 * Get call info. 168 */ 169 PJ_DEF(pj_status_t) pjsua_get_call_info( unsigned call_index, 170 pjsua_call_info *info) 171 { 172 pjsua_call *call; 173 174 PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, 175 PJ_EINVAL); 176 177 pj_memset(info, 0, sizeof(pjsua_call_info)); 178 179 call = &pjsua.calls[call_index]; 180 info->active = pjsua_call_is_active(call_index); 181 182 if (call->inv == NULL) 183 return PJ_SUCCESS; 184 185 info->index = call_index; 186 info->role = call->inv->role; 187 info->local_info = call->inv->dlg->local.info_str; 188 info->remote_info = call->inv->dlg->remote.info_str; 189 info->state = call->inv->state; 190 info->state_text = pj_str((char*)pjsip_inv_state_name(info->state)); 191 192 if (info->state >= PJSIP_INV_STATE_DISCONNECTED) { 193 194 info->total_duration = call->dis_time; 195 PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 196 197 if (call->conn_time.sec) { 198 info->connect_duration = call->dis_time; 199 PJ_TIME_VAL_SUB(info->total_duration, call->conn_time); 200 } 201 202 } else if (info->state == PJSIP_INV_STATE_CONFIRMED) { 203 204 pj_gettimeofday(&info->total_duration); 205 PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 206 207 pj_gettimeofday(&info->connect_duration); 208 PJ_TIME_VAL_SUB(info->connect_duration, call->conn_time); 209 210 } else { 211 pj_gettimeofday(&info->total_duration); 212 PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 213 } 214 215 info->cause = call->inv->cause; 216 info->cause_text = *pjsip_get_status_text(info->cause); 217 218 info->has_media = (call->session != NULL); 219 info->conf_slot = call->conf_slot; 220 221 return PJ_SUCCESS; 222 } 223 224 225 /** 226 * Duplicate call info. 227 */ 228 PJ_DEF(void) pjsua_dup_call_info( pj_pool_t *pool, 229 pjsua_call_info *dst_info, 230 const pjsua_call_info *src_info) 231 { 232 PJ_ASSERT_ON_FAIL(pool && dst_info && src_info, return); 233 234 pj_memcpy(dst_info, src_info, sizeof(pjsua_call_info)); 235 236 pj_strdup(pool, &dst_info->local_info, &src_info->local_info); 237 pj_strdup(pool, &dst_info->remote_info, &src_info->remote_info); 238 239 /* state_text and cause_text belong to pjsip, so don't need to be 240 * duplicated because they'll always be available. 241 */ 242 } 243 244 245 /** 128 246 * Make outgoing call. 129 247 */ 130 PJ_DEF(pj_status_t) pjsua_make_call( intacc_index,131 const char *cstr_dest_uri,248 PJ_DEF(pj_status_t) pjsua_make_call(unsigned acc_index, 249 const pj_str_t *dest_uri, 132 250 int *p_call_index) 133 251 { 134 pj_str_t dest_uri;135 252 pjsip_dialog *dlg = NULL; 136 253 pjmedia_sdp_session *offer; … … 140 257 pj_status_t status; 141 258 142 /* Convert cstr_dest_uri to dest_uri */ 143 144 dest_uri = pj_str((char*)cstr_dest_uri); 259 260 PJ_ASSERT_RETURN(acc_index==0 || acc_index < pjsua.config.acc_cnt, 261 PJ_EINVAL); 262 145 263 146 264 /* Find free call slot. */ … … 165 283 &pjsua.config.acc_config[acc_index].id, 166 284 &pjsua.config.acc_config[acc_index].contact, 167 &dest_uri, &dest_uri,285 dest_uri, dest_uri, 168 286 &dlg); 169 287 if (status != PJ_SUCCESS) { … … 656 774 pjsip_generic_string_hdr *refer_to; 657 775 char *uri; 776 pj_str_t tmp; 658 777 struct pjsip_evsub_user xfer_cb; 778 pjsip_status_code code; 659 779 pjsip_evsub *sub; 660 780 … … 674 794 } 675 795 796 /* Notify callback */ 797 code = PJSIP_SC_OK; 798 if (pjsua.cb.on_call_transfered) 799 (*pjsua.cb.on_call_transfered)(existing_call->index, 800 &refer_to->hvalue, &code); 801 802 if (code < 200) 803 code = 200; 804 if (code >= 300) { 805 /* Application rejects call transfer request */ 806 pjsip_dlg_respond( inv->dlg, rdata, code, NULL, NULL, NULL); 807 return; 808 } 809 676 810 PJ_LOG(3,(THIS_FILE, "Call to %.*s is being transfered to %.*s", 677 811 (int)inv->dlg->remote.info_str.slen, … … 693 827 694 828 /* Accept the REFER request, send 200 (OK). */ 695 pjsip_xfer_accept(sub, rdata, 200, NULL);829 pjsip_xfer_accept(sub, rdata, code, NULL); 696 830 697 831 /* Create initial NOTIFY request */ … … 719 853 720 854 /* Now make the outgoing call. */ 721 status = pjsua_make_call(existing_call->acc_index, uri, &new_call); 855 tmp = pj_str(uri); 856 status = pjsua_make_call(existing_call->acc_index, &tmp, &new_call); 722 857 if (status != PJ_SUCCESS) { 723 858 … … 1084 1219 { 1085 1220 1086 pjmedia_conf_connect_port( pjsua.mconf, pjsua. wav_slot,1221 pjmedia_conf_connect_port( pjsua.mconf, pjsua.player[0].slot, 1087 1222 call->conf_slot, 0); 1088 1223 … … 1308 1443 * Transfer call. 1309 1444 */ 1310 PJ_DEF(void) pjsua_call_xfer( int call_index, const char*dest)1445 PJ_DEF(void) pjsua_call_xfer(unsigned call_index, const pj_str_t *dest) 1311 1446 { 1312 1447 pjsip_evsub *sub; 1313 1448 pjsip_tx_data *tdata; 1314 1449 pjsua_call *call; 1315 pj_str_t tmp;1316 1450 pj_status_t status; 1317 1451 … … 1337 1471 * Create REFER request. 1338 1472 */ 1339 status = pjsip_xfer_initiate(sub, pj_cstr(&tmp, dest), &tdata);1473 status = pjsip_xfer_initiate(sub, dest, &tdata); 1340 1474 if (status != PJ_SUCCESS) { 1341 1475 pjsua_perror(THIS_FILE, "Unable to create REFER request", status); … … 1358 1492 1359 1493 /** 1494 * Dial DTMF. 1495 */ 1496 PJ_DEF(pj_status_t) pjsua_call_dial_dtmf( unsigned call_index, 1497 const pj_str_t *digits) 1498 { 1499 pjsua_call *call = &pjsua.calls[call_index]; 1500 1501 PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, PJ_EINVAL); 1502 1503 if (!call->session) { 1504 PJ_LOG(3,(THIS_FILE, "Media is not established yet!")); 1505 return -1; 1506 } 1507 1508 return pjmedia_session_dial_dtmf( call->session, 0, digits); 1509 } 1510 1511 1512 /** 1360 1513 * Send instant messaging inside INVITE session. 1361 1514 */ 1362 PJ_DECL(void) pjsua_call_send_im(int call_index, const char*str)1515 PJ_DECL(void) pjsua_call_send_im(int call_index, const pj_str_t *str) 1363 1516 { 1364 1517 pjsua_call *call; 1365 1518 const pj_str_t mime_text = pj_str("text"); 1366 1519 const pj_str_t mime_plain = pj_str("plain"); 1367 pj_str_t text;1368 1520 pjsip_tx_data *tdata; 1369 1521 pj_status_t status; … … 1393 1545 /* Create "text/plain" message body. */ 1394 1546 tdata->msg->body = pjsip_msg_body_create( tdata->pool, &mime_text, 1395 &mime_plain, 1396 pj_cstr(&text, str)); 1547 &mime_plain, str); 1397 1548 if (tdata->msg->body == NULL) { 1398 1549 pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM); … … 1505 1656 return status; 1506 1657 } 1658 1659 /** 1660 * Replace media transport. 1661 */ 1662 PJ_DEF(pj_status_t) pjsua_set_call_media_transport( unsigned call_index, 1663 const pjmedia_sock_info *i, 1664 pjmedia_transport *tp) 1665 { 1666 pjsua_call *call = &pjsua.calls[call_index]; 1667 1668 if (i) 1669 pj_memcpy(&call->skinfo, i, sizeof(pjmedia_sock_info)); 1670 1671 if (call->med_tp) 1672 (*call->med_tp->op->destroy)(call->med_tp); 1673 1674 call->med_tp = tp; 1675 return PJ_SUCCESS; 1676 } -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_console_app.c
r476 r482 35 35 static pj_bool_t find_next_call(void) 36 36 { 37 int i; 38 39 for (i=current_call+1; i<(int)pjsua.config.max_calls; ++i) { 40 if (pjsua.calls[i].inv != NULL) { 37 int i, max; 38 39 max = pjsua_get_max_calls(); 40 for (i=current_call+1; i<max; ++i) { 41 if (pjsua_call_is_active(i)) { 41 42 current_call = i; 42 43 return PJ_TRUE; … … 45 46 46 47 for (i=0; i<current_call; ++i) { 47 if (pjsua .calls[i].inv != NULL) {48 if (pjsua_call_is_active(i)) { 48 49 current_call = i; 49 50 return PJ_TRUE; … … 61 62 static pj_bool_t find_prev_call(void) 62 63 { 63 int i; 64 64 int i, max; 65 66 max = pjsua_get_max_calls(); 65 67 for (i=current_call-1; i>=0; --i) { 66 if (pjsua .calls[i].inv != NULL) {68 if (pjsua_call_is_active(i)) { 67 69 current_call = i; 68 70 return PJ_TRUE; … … 70 72 } 71 73 72 for (i= pjsua.config.max_calls-1; i>current_call; --i) {73 if (pjsua .calls[i].inv != NULL) {74 for (i=max-1; i>current_call; --i) { 75 if (pjsua_call_is_active(i)) { 74 76 current_call = i; 75 77 return PJ_TRUE; … … 88 90 static void console_on_call_state(int call_index, pjsip_event *e) 89 91 { 90 pjsua_call *call = &pjsua.calls[call_index];92 pjsua_call_info call_info; 91 93 92 94 PJ_UNUSED_ARG(e); 93 95 94 if (call->inv->state == PJSIP_INV_STATE_DISCONNECTED) { 96 pjsua_get_call_info(call_index, &call_info); 97 98 if (call_info.state == PJSIP_INV_STATE_DISCONNECTED) { 95 99 96 100 PJ_LOG(3,(THIS_FILE, "Call %d is DISCONNECTED [reason=%d (%s)]", 97 101 call_index, 98 call->inv->cause, 99 pjsip_get_status_text(call->inv->cause)->ptr)); 100 101 call->inv = NULL; 102 if ((int)call->index == current_call) { 102 call_info.cause, 103 call_info.cause_text.ptr)); 104 105 if ((int)call_index == current_call) { 103 106 find_next_call(); 104 107 } … … 108 111 PJ_LOG(3,(THIS_FILE, "Call %d state changed to %s", 109 112 call_index, 110 pjsua_inv_state_names[call->inv->state]));111 112 if (c all && current_call==-1)113 current_call = call ->index;113 call_info.state_text.ptr)); 114 115 if (current_call==-1) 116 current_call = call_index; 114 117 115 118 } … … 124 127 125 128 // Log already written. 129 } 130 131 132 /** 133 * Notify UI on buddy state changed. 134 */ 135 static void console_on_buddy_state(int buddy_index) 136 { 137 pjsua_buddy_info info; 138 pjsua_buddy_get_info(buddy_index, &info); 139 140 PJ_LOG(3,(THIS_FILE, "%.*s status is %.*s", 141 (int)info.uri.slen, 142 info.uri.ptr, 143 (int)info.status_text.slen, 144 info.status_text.ptr)); 126 145 } 127 146 … … 163 182 static void print_buddy_list(void) 164 183 { 165 int i ;184 int i, count; 166 185 167 186 puts("Buddy list:"); 168 187 169 if (pjsua.buddy_cnt == 0) 188 count = pjsua_get_buddy_count(); 189 190 if (count == 0) 170 191 puts(" -none-"); 171 192 else { 172 for (i=0; i<pjsua.buddy_cnt; ++i) { 173 const char *status; 174 175 if (pjsua.buddies[i].sub == NULL || 176 pjsua.buddies[i].status.info_cnt==0) 177 { 178 status = " ? "; 179 } 180 else if (pjsua.buddies[i].status.info[0].basic_open) 181 status = " Online"; 182 else 183 status = "Offline"; 184 185 printf(" [%2d] <%s> %s\n", 186 i+1, status, pjsua.buddies[i].uri.ptr); 193 for (i=0; i<count; ++i) { 194 pjsua_buddy_info info; 195 196 if (pjsua_buddy_get_info(i, &info) != PJ_SUCCESS) 197 continue; 198 199 if (!info.is_valid) 200 continue; 201 202 printf(" [%2d] <%7s> %.*s\n", 203 i+1, info.status_text.ptr, 204 (int)info.uri.slen, 205 info.uri.ptr); 187 206 } 188 207 } … … 196 215 static void print_acc_status(int acc_index) 197 216 { 198 char reg_status[128]; 199 200 if (pjsua.acc[acc_index].regc == NULL) { 201 pj_ansi_strcpy(reg_status, " -not registered to server-"); 202 203 } else if (pjsua.acc[acc_index].reg_last_err != PJ_SUCCESS) { 204 pj_strerror(pjsua.acc[acc_index].reg_last_err, reg_status, sizeof(reg_status)); 205 206 } else if (pjsua.acc[acc_index].reg_last_code>=200 && 207 pjsua.acc[acc_index].reg_last_code<=699) { 208 209 pjsip_regc_info info; 210 const pj_str_t *status_str; 211 212 pjsip_regc_get_info(pjsua.acc[acc_index].regc, &info); 213 214 status_str = pjsip_get_status_text(pjsua.acc[acc_index].reg_last_code); 215 pj_ansi_snprintf(reg_status, sizeof(reg_status), 216 "%s (%.*s;expires=%d)", 217 status_str->ptr, 218 (int)info.client_uri.slen, 219 info.client_uri.ptr, 220 info.next_reg); 217 char buf[80]; 218 pjsua_acc_info info; 219 220 pjsua_acc_get_info(acc_index, &info); 221 222 if (!info.has_registration) { 223 pj_ansi_strcpy(buf, " -not registered to server-"); 221 224 222 225 } else { 223 pj_ansi_sprintf(reg_status, "in progress (%d)", 224 pjsua.acc[acc_index].reg_last_code); 225 } 226 227 printf("[%2d] Registration status: %s\n", acc_index, reg_status); 226 pj_ansi_snprintf(buf, sizeof(buf), 227 "%.*s (%.*s;expires=%d)", 228 (int)info.status_text.slen, 229 info.status_text.ptr, 230 (int)info.acc_id.slen, 231 info.acc_id.ptr, 232 info.expires); 233 234 } 235 236 printf("[%2d] Registration status: %s\n", acc_index, buf); 228 237 printf(" Online status: %s\n", 229 ( pjsua.acc[acc_index].online_status ? "Online" : "Invisible"));238 (info.online_status ? "Online" : "Invisible")); 230 239 } 231 240 … … 239 248 printf(">>>>\n"); 240 249 241 for (i=0; i<(int)pjsua .config.acc_cnt; ++i)250 for (i=0; i<(int)pjsua_get_acc_count(); ++i) 242 251 print_acc_status(i); 243 252 … … 312 321 " URL An URL\n" 313 322 " <Enter> Empty input (or 'q') to cancel\n" 314 , pjsua .buddy_cnt, pjsua.buddy_cnt);323 , pjsua_get_buddy_count(), pjsua_get_buddy_count()); 315 324 printf("%s: ", title); 316 325 … … 350 359 result->nb_result = atoi(buf); 351 360 352 if (result->nb_result >= 0 && result->nb_result <= (int)pjsua.buddy_cnt) { 361 if (result->nb_result >= 0 && 362 result->nb_result <= (int)pjsua_get_buddy_count()) 363 { 353 364 return; 354 365 } … … 380 391 381 392 count = PJ_ARRAY_SIZE(info); 382 pj media_conf_get_ports_info(pjsua.mconf,&count, info);393 pjsua_conf_enum_ports(&count, info); 383 394 for (i=0; i<count; ++i) { 384 395 char txlist[PJSUA_MAX_CALLS*4+10]; … … 414 425 int i, count; 415 426 char *uri; 427 pj_str_t tmp; 416 428 struct input_result result; 429 pjsua_call_info call_info; 430 pjsua_acc_info acc_info; 417 431 418 432 419 433 /* If user specifies URI to call, then call the URI */ 420 if (pjsua.config.uri_to_call.slen) { 421 pjsua_make_call( current_acc, pjsua.config.uri_to_call.ptr, NULL); 434 if (pjsua_get_config()->uri_to_call.slen) { 435 pjsua_make_call( current_acc, &pjsua_get_config()->uri_to_call, 436 NULL); 422 437 } 423 438 … … 435 450 case 'm': 436 451 /* Make call! : */ 437 printf("(You currently have %d calls)\n", pjsua .call_cnt);452 printf("(You currently have %d calls)\n", pjsua_get_call_count()); 438 453 439 454 uri = NULL; … … 445 460 continue; 446 461 } else { 447 uri = pjsua.buddies[result.nb_result-1].uri.ptr; 462 pjsua_buddy_info binfo; 463 pjsua_buddy_get_info(result.nb_result-1, &binfo); 464 uri = binfo.uri.ptr; 448 465 } 449 466 … … 452 469 } 453 470 454 pjsua_make_call( current_acc, uri, NULL); 471 tmp = pj_str(uri); 472 pjsua_make_call( current_acc, &tmp, NULL); 455 473 break; 456 474 457 475 case 'M': 458 476 /* Make multiple calls! : */ 459 printf("(You currently have %d calls)\n", pjsua .call_cnt);477 printf("(You currently have %d calls)\n", pjsua_get_call_count()); 460 478 461 479 if (!simple_input("Number of calls", menuin, sizeof(menuin))) … … 468 486 ui_input_url("Make call", buf, sizeof(buf), &result); 469 487 if (result.nb_result != NO_NB) { 488 pjsua_buddy_info binfo; 470 489 if (result.nb_result == -1 || result.nb_result == 0) { 471 490 puts("You can't do that with make call!"); 472 491 continue; 473 492 } 474 uri = pjsua.buddies[result.nb_result-1].uri.ptr; 493 pjsua_buddy_get_info(result.nb_result-1, &binfo); 494 uri = binfo.uri.ptr; 475 495 } else { 476 496 uri = result.uri_result; … … 479 499 for (i=0; i<atoi(menuin); ++i) { 480 500 pj_status_t status; 481 482 status = pjsua_make_call(current_acc, uri, NULL); 501 502 tmp = pj_str(uri); 503 status = pjsua_make_call(current_acc, &tmp, NULL); 483 504 if (status != PJ_SUCCESS) 484 505 break; … … 508 529 509 530 } else { 510 uri = pjsua.buddies[result.nb_result-1].uri.ptr; 531 pjsua_buddy_info binfo; 532 pjsua_buddy_get_info(result.nb_result-1, &binfo); 533 uri = binfo.uri.ptr; 511 534 } 512 535 … … 519 542 if (i != -1) 520 543 pjsua_call_typing(i, PJ_TRUE); 521 else 522 pjsua_im_typing(current_acc, uri, PJ_TRUE); 544 else { 545 pj_str_t tmp_uri = pj_str(uri); 546 pjsua_im_typing(current_acc, &tmp_uri, PJ_TRUE); 547 } 523 548 524 549 /* Input the IM . */ … … 530 555 if (i != -1) 531 556 pjsua_call_typing(i, PJ_FALSE); 532 else 533 pjsua_im_typing(current_acc, uri, PJ_FALSE); 557 else { 558 pj_str_t tmp_uri = pj_str(uri); 559 pjsua_im_typing(current_acc, &tmp_uri, PJ_FALSE); 560 } 534 561 continue; 535 562 } 563 564 tmp = pj_str(text); 536 565 537 566 /* Send the IM */ 538 567 if (i != -1) 539 pjsua_call_send_im(i, text); 540 else 541 pjsua_im_send(current_acc, uri, text); 568 pjsua_call_send_im(i, &tmp); 569 else { 570 pj_str_t tmp_uri = pj_str(uri); 571 pjsua_im_send(current_acc, &tmp_uri, &tmp); 572 } 542 573 543 574 break; … … 545 576 case 'a': 546 577 578 if (current_call != -1) { 579 pjsua_get_call_info(current_call, &call_info); 580 } else { 581 /* Make compiler happy */ 582 call_info.active = 0; 583 call_info.role = PJSIP_ROLE_UAC; 584 call_info.state = PJSIP_INV_STATE_DISCONNECTED; 585 } 586 547 587 if (current_call == -1 || 548 pjsua.calls[current_call].inv->role != PJSIP_ROLE_UAS || 549 pjsua.calls[current_call].inv->state >= PJSIP_INV_STATE_CONNECTING) 588 call_info.active==0 || 589 call_info.role != PJSIP_ROLE_UAS || 590 call_info.state >= PJSIP_INV_STATE_CONNECTING) 550 591 { 551 592 puts("No pending incoming call"); … … 609 650 610 651 if (current_call != -1) { 611 char url[PJSIP_MAX_URL_SIZE]; 612 int len; 613 const pjsip_uri *u; 614 615 u = pjsua.calls[current_call].inv->dlg->remote.info->uri; 616 len = pjsip_uri_print(0, u, url, sizeof(url)-1); 617 if (len < 1) { 618 pj_ansi_strcpy(url, "<uri is too long>"); 619 } else { 620 url[len] = '\0'; 621 } 622 623 PJ_LOG(3,(THIS_FILE,"Current dialog: %s", url)); 652 653 pjsua_get_call_info(current_call, &call_info); 654 PJ_LOG(3,(THIS_FILE,"Current dialog: %.*s", 655 (int)call_info.remote_info.slen, 656 call_info.remote_info.ptr)); 624 657 625 658 } else { … … 677 710 if (result.nb_result == -1 || result.nb_result == 0) 678 711 puts("You can't do that with transfer call!"); 679 else 712 else { 713 pjsua_buddy_info binfo; 714 pjsua_buddy_get_info(result.nb_result-1, &binfo); 680 715 pjsua_call_xfer( current_call, 681 pjsua.buddies[result.nb_result-1].uri.ptr); 716 &binfo.uri); 717 } 682 718 683 719 } else if (result.uri_result) { 684 pjsua_call_xfer( current_call, result.uri_result); 720 pj_str_t tmp; 721 tmp = pj_str(result.uri_result); 722 pjsua_call_xfer( current_call, &tmp); 685 723 } 686 724 } … … 695 733 PJ_LOG(3,(THIS_FILE, "No current call")); 696 734 697 } else if ( pjsua.calls[current_call].session == NULL) {735 } else if (!pjsua_call_has_media(current_call)) { 698 736 699 737 PJ_LOG(3,(THIS_FILE, "Media is not established yet!")); … … 716 754 717 755 digits = pj_str(buf); 718 status = pjmedia_session_dial_dtmf(pjsua.calls[current_call].session, 0, 719 &digits); 756 status = pjsua_call_dial_dtmf(current_call, &digits); 720 757 if (status != PJ_SUCCESS) { 721 758 pjsua_perror(THIS_FILE, "Unable to send DTMF", status); … … 734 771 if (result.nb_result != NO_NB) { 735 772 if (result.nb_result == -1) { 736 int i; 737 for (i=0; i<pjsua.buddy_cnt; ++i) 738 pjsua.buddies[i].monitor = (menuin[0]=='s'); 773 int i, count; 774 count = pjsua_get_buddy_count(); 775 for (i=0; i<count; ++i) 776 pjsua_buddy_subscribe_pres(i, menuin[0]=='s'); 739 777 } else if (result.nb_result == 0) { 740 778 puts("Sorry, can only subscribe to buddy's presence, " 741 779 "not from existing call"); 742 780 } else { 743 pjsua .buddies[result.nb_result-1].monitor = (menuin[0]=='s');781 pjsua_buddy_subscribe_pres(result.nb_result-1, (menuin[0]=='s')); 744 782 } 745 783 … … 759 797 * Re-Register. 760 798 */ 761 pjsua_ regc_update(current_acc, PJ_TRUE);799 pjsua_acc_set_registration(current_acc, PJ_TRUE); 762 800 break; 763 801 case 'u': … … 765 803 * Unregister 766 804 */ 767 pjsua_ regc_update(current_acc, PJ_FALSE);805 pjsua_acc_set_registration(current_acc, PJ_FALSE); 768 806 break; 769 807 } … … 771 809 772 810 case 't': 773 pjsua.acc[current_acc].online_status = 774 !pjsua.acc[current_acc].online_status; 811 pjsua_acc_get_info(current_acc, &acc_info); 812 acc_info.online_status = !acc_info.online_status; 813 pjsua_acc_set_online_status(current_acc, acc_info.online_status); 775 814 printf("Setting %s online status to %s\n", 776 pjsua.config.acc_config[current_acc].id.ptr,777 ( pjsua.acc[current_acc].online_status?"online":"offline"));815 acc_info.acc_id.ptr, 816 (acc_info.online_status?"online":"offline")); 778 817 pjsua_pres_refresh(current_acc); 779 818 break; … … 807 846 808 847 if (menuin[1]=='c') { 809 status = pjmedia_conf_connect_port(pjsua.mconf, 810 atoi(src_port), 811 atoi(dst_port), 812 0); 848 status = pjsua_conf_connect(atoi(src_port), 849 atoi(dst_port)); 813 850 } else { 814 status = pjmedia_conf_disconnect_port(pjsua.mconf, 815 atoi(src_port), 816 atoi(dst_port)); 851 status = pjsua_conf_disconnect(atoi(src_port), 852 atoi(dst_port)); 817 853 } 818 854 if (status == PJ_SUCCESS) { … … 831 867 int len; 832 868 833 len = pjsua_dump_settings( &pjsua.config, settings,869 len = pjsua_dump_settings(NULL, settings, 834 870 sizeof(settings)); 835 871 if (len < 1) … … 947 983 /* Write to both stdout and file. */ 948 984 949 if (level <= (int)pjsua .config.app_log_level)985 if (level <= (int)pjsua_get_config()->app_log_level) 950 986 pj_log_write(level, buffer, len); 951 987 … … 1010 1046 { 1011 1047 &console_on_call_state, 1048 NULL, /* default accept transfer */ 1012 1049 &console_on_reg_state, 1050 &console_on_buddy_state, 1013 1051 &console_on_pager, 1014 1052 &console_on_typing, -
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 -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_im.c
r476 r482 19 19 #include <pjsua-lib/pjsua.h> 20 20 #include <pj/log.h> 21 #include "pjsua_imp.h" 21 22 22 23 /* … … 272 273 * Send IM outside dialog. 273 274 */ 274 PJ_DEF(pj_status_t) pjsua_im_send(int acc_index, const char*dst_uri,275 const char*str)275 PJ_DEF(pj_status_t) pjsua_im_send(int acc_index, const pj_str_t *dst_uri, 276 const pj_str_t *str) 276 277 { 277 278 pjsip_tx_data *tdata; … … 280 281 const pj_str_t mime_plain = pj_str("plain"); 281 282 pj_str_t *text; 282 const pj_str_t dst = pj_str((char*)dst_uri);283 283 pj_status_t status; 284 284 285 285 /* Create request. */ 286 286 status = pjsip_endpt_create_request(pjsua.endpt, &pjsip_message_method, 287 &dst,287 dst_uri, 288 288 &pjsua.config.acc_config[acc_index].id, 289 &dst, NULL, NULL, -1, NULL, &tdata);289 dst_uri, NULL, NULL, -1, NULL, &tdata); 290 290 if (status != PJ_SUCCESS) { 291 291 pjsua_perror(THIS_FILE, "Unable to create request", status); … … 308 308 */ 309 309 text = pj_pool_alloc(tdata->pool, sizeof(pj_str_t)); 310 pj_strdup 2_with_null(tdata->pool, text, str);310 pj_strdup_with_null(tdata->pool, text, str); 311 311 312 312 /* Add message body */ … … 334 334 * Send typing indication outside dialog. 335 335 */ 336 PJ_DEF(pj_status_t) pjsua_im_typing(int acc_index, const char*dst_uri,336 PJ_DEF(pj_status_t) pjsua_im_typing(int acc_index, const pj_str_t *dst_uri, 337 337 pj_bool_t is_typing) 338 338 { 339 const pj_str_t dst = pj_str((char*)dst_uri);340 339 pjsip_tx_data *tdata; 341 340 pj_status_t status; … … 343 342 /* Create request. */ 344 343 status = pjsip_endpt_create_request( pjsua.endpt, &pjsip_message_method, 345 &dst,344 dst_uri, 346 345 &pjsua.config.acc_config[acc_index].id, 347 &dst, NULL, NULL, -1, NULL, &tdata);346 dst_uri, NULL, NULL, -1, NULL, &tdata); 348 347 if (status != PJ_SUCCESS) { 349 348 pjsua_perror(THIS_FILE, "Unable to create request", status); -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_imp.h
r476 r482 22 22 23 23 24 25 26 /** 27 * Structure to be attached to invite dialog. 28 * Given a dialog "dlg", application can retrieve this structure 29 * by accessing dlg->mod_data[pjsua.mod.id]. 30 */ 31 struct pjsua_call 32 { 33 unsigned index; /**< Index in pjsua array. */ 34 pjsip_inv_session *inv; /**< The invite session. */ 35 pj_time_val start_time;/**< First INVITE sent/received. */ 36 pj_time_val res_time; /**< First response sent/received. */ 37 pj_time_val conn_time; /**< Connected/confirmed time. */ 38 pj_time_val dis_time; /**< Disconnect time. */ 39 int acc_index; /**< Account index being used. */ 40 pjmedia_session *session; /**< The media session. */ 41 unsigned conf_slot; /**< Slot # in conference bridge. */ 42 pjsip_evsub *xfer_sub; /**< Xfer server subscription, if this 43 call was triggered by xfer. */ 44 pjmedia_sock_info skinfo; /**< Preallocated media sockets. */ 45 pjmedia_transport *med_tp; /**< Media transport. */ 46 void *app_data; /**< Application data. */ 47 pj_timer_entry refresh_tm;/**< Timer to send re-INVITE. */ 48 pj_timer_entry hangup_tm; /**< Timer to hangup call. */ 49 }; 50 51 typedef struct pjsua_call pjsua_call; 52 53 54 /** 55 * Buddy data. 56 */ 57 struct pjsua_buddy 58 { 59 unsigned index; /**< Buddy index. */ 60 pj_str_t name; /**< Buddy name. */ 61 pj_str_t display; /**< Buddy display name. */ 62 pj_str_t host; /**< Buddy host. */ 63 unsigned port; /**< Buddy port. */ 64 int acc_index; /**< Which account to use. */ 65 pj_bool_t monitor; /**< Should we monitor? */ 66 pjsip_evsub *sub; /**< Buddy presence subscription */ 67 pjsip_pres_status status; /**< Buddy presence status. */ 68 }; 69 70 typedef struct pjsua_buddy pjsua_buddy; 71 72 73 /** 74 * Server presence subscription list head. 75 */ 76 struct pjsua_srv_pres 77 { 78 PJ_DECL_LIST_MEMBER(struct pjsua_srv_pres); 79 pjsip_evsub *sub; 80 char *remote; 81 }; 82 83 typedef struct pjsua_srv_pres pjsua_srv_pres; 84 85 86 87 /** 88 * Account 89 */ 90 struct pjsua_acc 91 { 92 int index; /**< Index in accounts array. */ 93 pj_str_t user_part; /**< User part of local URI. */ 94 pj_str_t host_part; /**< Host part of local URI. */ 95 96 pjsip_regc *regc; /**< Client registration session. */ 97 pj_timer_entry reg_timer; /**< Registration timer. */ 98 pj_status_t reg_last_err; /**< Last registration error. */ 99 int reg_last_code; /**< Last status last register. */ 100 101 pjsip_route_hdr route_set; /**< Route set. */ 102 103 pj_bool_t online_status; /**< Our online status. */ 104 pjsua_srv_pres pres_srv_list; /**< Server subscription list. */ 105 106 void *app_data; /**< Application data. */ 107 }; 108 109 110 /** 111 * @see pjsua_acc 112 */ 113 typedef struct pjsua_acc pjsua_acc; 114 115 116 /* PJSUA application variables. */ 117 struct pjsua 118 { 119 /* Control: */ 120 pj_caching_pool cp; /**< Global pool factory. */ 121 pjsip_endpoint *endpt; /**< Global endpoint. */ 122 pj_pool_t *pool; /**< pjsua's private pool. */ 123 pjsip_module mod; /**< pjsua's PJSIP module. */ 124 125 126 /* Config: */ 127 pjsua_config config; /**< PJSUA configs */ 128 129 /* Application callback 130 : */ 131 pjsua_callback cb; /**< Application callback. */ 132 133 /* Media: */ 134 pjmedia_endpt *med_endpt; /**< Media endpoint. */ 135 unsigned clock_rate; /**< Conference bridge's clock rate.*/ 136 unsigned samples_per_frame; /**< Bridge's frame size. */ 137 pjmedia_conf *mconf; /**< Media conference. */ 138 139 pjmedia_snd_port *snd_port; /**< Sound device port. */ 140 pjmedia_master_port *master_port; /**< Master port, when no snd dev */ 141 142 unsigned player_cnt; /**< Number of file player. */ 143 144 /** Array of file players */ 145 struct { 146 unsigned slot; /**< WAV player slot in bridge */ 147 pjmedia_port *port; /**< WAV player port. */ 148 } player[32]; 149 150 unsigned recorder_cnt; /**< Number of file recorders. */ 151 152 /** Array of file recorders */ 153 struct { 154 unsigned slot; /**< Slot # in conf bridge. */ 155 pjmedia_port *port; /**< The recorder media port. */ 156 } recorder[32]; 157 158 /* Account: */ 159 pjsua_acc acc[PJSUA_MAX_ACC]; /** Client regs array. */ 160 161 162 /* Threading (optional): */ 163 pj_thread_t *threads[8]; /**< Thread instances. */ 164 pj_bool_t quit_flag; /**< To signal thread to quit. */ 165 166 /* Transport (UDP): */ 167 pj_sock_t sip_sock; /**< SIP UDP socket. */ 168 pj_sockaddr_in sip_sock_name; /**< Public/STUN UDP socket addr. */ 169 170 171 /* PJSUA Calls: */ 172 unsigned call_cnt; /**< Number of calls. */ 173 pjsua_call calls[PJSUA_MAX_CALLS]; /** Calls array. */ 174 175 176 /* SIMPLE and buddy status: */ 177 pjsua_buddy buddies[PJSUA_MAX_BUDDIES]; 178 }; 179 180 181 /** PJSUA instance. */ 182 extern struct pjsua pjsua; 183 184 185 24 186 /** 25 187 * Find account for incoming request. -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c
r476 r482 236 236 if (buddy) { 237 237 PJ_LOG(3,(THIS_FILE, 238 "Presence subscription to %s is %s", 239 buddy->uri.ptr, 238 "Presence subscription to %.*s is %s", 239 (int)pjsua.config.buddy_uri[buddy->index].slen, 240 pjsua.config.buddy_uri[buddy->index].ptr, 240 241 pjsip_evsub_get_state_name(sub))); 241 242 … … 245 246 pjsip_evsub_set_mod_data(sub, pjsua.mod.id, NULL); 246 247 } 248 249 /* Call callback */ 250 if (pjsua.cb.on_buddy_state) 251 (*pjsua.cb.on_buddy_state)(buddy->index); 247 252 } 248 253 } … … 262 267 /* Update our info. */ 263 268 pjsip_pres_get_status(sub, &buddy->status); 264 265 if (buddy->status.info_cnt) {266 PJ_LOG(3,(THIS_FILE, "%s is %s",267 buddy->uri.ptr,268 (buddy->status.info[0].basic_open?"online":"offline")));269 } else {270 PJ_LOG(3,(THIS_FILE, "No presence info for %s",271 buddy->uri.ptr));272 }273 269 } 274 270 … … 321 317 &acc_config->id, 322 318 &acc_config->contact, 323 &pjsua. buddies[index].uri,319 &pjsua.config.buddy_uri[index], 324 320 NULL, &dlg); 325 321 if (status != PJ_SUCCESS) { … … 401 397 static void refresh_client_subscription(void) 402 398 { 403 inti;404 405 for (i=0; i<pjsua. buddy_cnt; ++i) {399 unsigned i; 400 401 for (i=0; i<pjsua.config.buddy_cnt; ++i) { 406 402 407 403 if (pjsua.buddies[i].monitor && !pjsua.buddies[i].sub) { … … 433 429 434 430 /* 431 * Get buddy count. 432 */ 433 PJ_DEF(unsigned) pjsua_get_buddy_count(void) 434 { 435 return pjsua.config.buddy_cnt; 436 } 437 438 439 /** 440 * Get buddy info. 441 */ 442 PJ_DEF(pj_status_t) pjsua_buddy_get_info(unsigned index, 443 pjsua_buddy_info *info) 444 { 445 pjsua_buddy *buddy; 446 447 PJ_ASSERT_RETURN(index < pjsua.config.buddy_cnt, PJ_EINVAL); 448 449 pj_memset(info, 0, sizeof(pjsua_buddy_info)); 450 451 buddy = &pjsua.buddies[index]; 452 info->index = buddy->index; 453 info->is_valid = pjsua.config.buddy_uri[index].slen; 454 if (!info->is_valid) 455 return PJ_SUCCESS; 456 457 info->name = buddy->name; 458 info->display_name = buddy->display; 459 info->host = buddy->host; 460 info->port = buddy->port; 461 info->uri = pjsua.config.buddy_uri[index]; 462 463 if (buddy->sub == NULL || buddy->status.info_cnt==0) { 464 info->status = PJSUA_BUDDY_STATUS_UNKNOWN; 465 info->status_text = pj_str("?"); 466 } else if (pjsua.buddies[index].status.info[0].basic_open) { 467 info->status = PJSUA_BUDDY_STATUS_ONLINE; 468 info->status_text = pj_str("Online"); 469 } else { 470 info->status = PJSUA_BUDDY_STATUS_OFFLINE; 471 info->status_text = pj_str("Offline"); 472 } 473 474 return PJ_SUCCESS; 475 } 476 477 478 /** 479 * Add new buddy. 480 */ 481 PJ_DEF(pj_status_t) pjsua_buddy_add( const pj_str_t *uri, 482 int *buddy_index) 483 { 484 pjsip_name_addr *url; 485 pjsip_sip_uri *sip_uri; 486 int index; 487 pj_str_t tmp; 488 489 PJ_ASSERT_RETURN(pjsua.config.buddy_cnt <= PJ_ARRAY_SIZE(pjsua.config.buddy_uri), 490 PJ_ETOOMANY); 491 492 index = pjsua.config.buddy_cnt; 493 494 /* Get name and display name for buddy */ 495 pj_strdup_with_null(pjsua.pool, &tmp, uri); 496 url = (pjsip_name_addr*)pjsip_parse_uri(pjsua.pool, tmp.ptr, tmp.slen, 497 PJSIP_PARSE_URI_AS_NAMEADDR); 498 499 if (url == NULL) 500 return PJSIP_EINVALIDURI; 501 502 /* Save URI */ 503 pjsua.config.buddy_uri[index] = tmp; 504 505 sip_uri = (pjsip_sip_uri*) url->uri; 506 pjsua.buddies[index].name = sip_uri->user; 507 pjsua.buddies[index].display = url->display; 508 pjsua.buddies[index].host = sip_uri->host; 509 pjsua.buddies[index].port = sip_uri->port; 510 if (pjsua.buddies[index].port == 0) 511 pjsua.buddies[index].port = 5060; 512 513 /* Find account for outgoing preence subscription */ 514 pjsua.buddies[index].acc_index = 515 pjsua_find_account_for_outgoing(&pjsua.config.buddy_uri[index]); 516 517 if (buddy_index) 518 *buddy_index = index; 519 520 pjsua.config.buddy_cnt++; 521 522 return PJ_SUCCESS; 523 } 524 525 526 527 PJ_DEF(pj_status_t) pjsua_buddy_subscribe_pres( unsigned index, 528 pj_bool_t monitor) 529 { 530 pjsua_buddy *buddy; 531 532 PJ_ASSERT_RETURN(index < pjsua.config.buddy_cnt, PJ_EINVAL); 533 534 buddy = &pjsua.buddies[index]; 535 buddy->monitor = monitor; 536 return PJ_SUCCESS; 537 } 538 539 540 PJ_DEF(pj_status_t) pjsua_acc_set_online_status( unsigned acc_index, 541 pj_bool_t is_online) 542 { 543 PJ_ASSERT_RETURN(acc_index < pjsua.config.acc_cnt, PJ_EINVAL); 544 pjsua.acc[acc_index].online_status = is_online; 545 return PJ_SUCCESS; 546 } 547 548 549 /* 435 550 * Refresh presence 436 551 */ … … 447 562 void pjsua_pres_shutdown(void) 448 563 { 449 intacc_index;450 inti;564 unsigned acc_index; 565 unsigned i; 451 566 452 567 for (acc_index=0; acc_index<(int)pjsua.config.acc_cnt; ++acc_index) { … … 454 569 } 455 570 456 for (i=0; i<pjsua. buddy_cnt; ++i) {571 for (i=0; i<pjsua.config.buddy_cnt; ++i) { 457 572 pjsua.buddies[i].monitor = 0; 458 573 } … … 468 583 void pjsua_pres_dump(pj_bool_t detail) 469 584 { 470 intacc_index;471 inti;585 unsigned acc_index; 586 unsigned i; 472 587 473 588 … … 498 613 count = 0; 499 614 500 for (i=0; i<pjsua. buddy_cnt; ++i) {615 for (i=0; i<pjsua.config.buddy_cnt; ++i) { 501 616 if (pjsua.buddies[i].sub) { 502 617 ++count; … … 545 660 PJ_LOG(3,(THIS_FILE, "Dumping pjsua client subscriptions:")); 546 661 547 if (pjsua. buddy_cnt == 0) {662 if (pjsua.config.buddy_cnt == 0) { 548 663 549 664 PJ_LOG(3,(THIS_FILE, " - no buddy list - ")); 550 665 551 666 } else { 552 for (i=0; i<pjsua. buddy_cnt; ++i) {667 for (i=0; i<pjsua.config.buddy_cnt; ++i) { 553 668 554 669 if (pjsua.buddies[i].sub) { 555 PJ_LOG(3,(THIS_FILE, " %10s % s",670 PJ_LOG(3,(THIS_FILE, " %10s %.*s", 556 671 pjsip_evsub_get_state_name(pjsua.buddies[i].sub), 557 pjsua.buddies[i].uri.ptr)); 672 (int)pjsua.config.buddy_uri[i].slen, 673 pjsua.config.buddy_uri[i].ptr)); 558 674 } else { 559 PJ_LOG(3,(THIS_FILE, " %10s % s",675 PJ_LOG(3,(THIS_FILE, " %10s %.*s", 560 676 "(null)", 561 pjsua.buddies[i].uri.ptr)); 677 (int)pjsua.config.buddy_uri[i].slen, 678 pjsua.config.buddy_uri[i].ptr)); 562 679 } 563 680 } -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_reg.c
r476 r482 18 18 */ 19 19 #include <pjsua-lib/pjsua.h> 20 #include "pjsua_imp.h" 20 21 21 22 … … 83 84 84 85 86 /** 87 * Get number of accounts. 88 */ 89 PJ_DEF(unsigned) pjsua_get_acc_count(void) 90 { 91 return pjsua.config.acc_cnt; 92 } 93 94 95 /** 96 * Get account info. 97 */ 98 PJ_DEF(pj_status_t) pjsua_acc_get_info( unsigned acc_index, 99 pjsua_acc_info *info) 100 { 101 pjsua_acc *acc = &pjsua.acc[acc_index]; 102 pjsua_acc_config *acc_cfg = &pjsua.config.acc_config[acc_index]; 103 104 PJ_ASSERT_RETURN(acc_index < pjsua.config.acc_cnt, PJ_EINVAL); 105 106 pj_memset(info, 0, sizeof(pjsua_acc_info)); 107 108 info->index = acc_index; 109 info->acc_id = acc_cfg->id; 110 info->has_registration = (acc->regc != NULL); 111 info->online_status = acc->online_status; 112 113 if (acc->reg_last_err) { 114 info->status = acc->reg_last_err; 115 pj_strerror(acc->reg_last_err, info->buf, sizeof(info->buf)); 116 info->status_text = pj_str(info->buf); 117 } else { 118 info->status = acc->reg_last_code; 119 info->status_text = *pjsip_get_status_text(acc->reg_last_code); 120 } 121 122 if (acc->regc) { 123 pjsip_regc_info regc_info; 124 pjsip_regc_get_info(acc->regc, ®c_info); 125 info->expires = regc_info.next_reg; 126 } 127 128 return PJ_SUCCESS; 129 } 130 131 85 132 /* 86 133 * Update registration. If renew is false, then unregistration will be performed. 87 134 */ 88 PJ_DECL(void) pjsua_ regc_update(intacc_index, pj_bool_t renew)135 PJ_DECL(void) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew) 89 136 { 90 137 pj_status_t status = 0; -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_settings.c
r476 r482 19 19 #include <pjsua-lib/pjsua.h> 20 20 #include <stdio.h> 21 #include "pjsua_imp.h" 22 21 23 22 24 /* … … 1008 1010 PJ_UNUSED_ARG(max); 1009 1011 1012 if (config == NULL) 1013 config = &pjsua.config; 1014 1010 1015 cfg.ptr = buf; 1011 1016 cfg.slen = 0; … … 1211 1216 return PJ_SUCCESS; 1212 1217 } 1218 1219 /** 1220 * Get pjsua running config. 1221 */ 1222 PJ_DEF(const pjsua_config*) pjsua_get_config(void) 1223 { 1224 return &pjsua.config; 1225 } 1226
Note: See TracChangeset
for help on using the changeset viewer.