Changeset 482 for pjproject/trunk


Ignore:
Timestamp:
May 28, 2006 2:58:12 PM (19 years ago)
Author:
bennylp
Message:

More changes in pjsua API to make it more complete high level API

Location:
pjproject/trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip-apps/src/pjsua/main.c

    r476 r482  
    2828int main(int argc, char *argv[]) 
    2929{ 
    30  
    3130    pjsua_config cfg; 
    3231 
     
    5655     * messages. 
    5756     */ 
    58     pjsip_endpt_register_module(pjsua.endpt,  
     57    pjsip_endpt_register_module(pjsua_get_pjsip_endpt(), 
    5958                                &pjsua_console_app_msg_logger); 
    6059 
     
    6261    /* Start pjsua! */ 
    6362    if (pjsua_start() != PJ_SUCCESS) { 
    64  
    6563        pjsua_destroy(); 
    6664        return 1; 
     
    7977    pjsua_destroy(); 
    8078 
     79    /* This is for internal testing, to make sure that pjsua_destroy() 
     80     * can be called multiple times.  
     81     */ 
     82    pjsua_destroy(); 
     83 
    8184 
    8285    /* Close logging: */ 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r476 r482  
    6969 
    7070 
    71  
    72 /**  
    73  * Structure to be attached to invite dialog.  
    74  * Given a dialog "dlg", application can retrieve this structure 
    75  * by accessing dlg->mod_data[pjsua.mod.id]. 
    76  */ 
    77 struct pjsua_call 
    78 { 
    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 this 
    89                                          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_buddy 
    104 { 
    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_pres 
    119 { 
    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  
    12871/** 
    12972 * Account configuration. 
     
    159102 */ 
    160103typedef struct pjsua_acc_config pjsua_acc_config; 
    161  
    162  
    163 /** 
    164  * Account 
    165  */ 
    166 struct pjsua_acc 
    167 { 
    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_acc 
    188  */ 
    189 typedef struct pjsua_acc pjsua_acc; 
    190104 
    191105 
     
    248162    unsigned    stun_port2; 
    249163 
     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 
    250170    /** Internal clock rate (to be applied to sound devices and conference 
    251171     *  bridge, default is 0/follows the codec, or 44100 for MacOS). 
     
    340260{ 
    341261    /** 
    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. 
    343265     */ 
    344266    void (*on_call_state)(int call_index, pjsip_event *e); 
    345267 
    346268    /** 
    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. 
    348283     */ 
    349284    void (*on_reg_state)(int acc_index); 
    350285 
    351286    /** 
    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). 
    353294     * Argument call_index will be -1 if MESSAGE request is not related to an  
    354295     * existing call. 
     
    358299 
    359300    /** 
    360      * Notify UI about typing indication. 
     301     * Notify application about typing indication. 
    361302     */ 
    362303    void (*on_typing)(int call_index, const pj_str_t *from, 
     
    371312 
    372313 
    373 /* PJSUA application variables. */ 
    374 struct pjsua 
     314/** 
     315 * Call info. 
     316 */ 
     317struct pjsua_call_info 
    375318{ 
    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; 
    417332}; 
    418333 
    419  
    420 /** PJSUA instance. */ 
    421 extern struct pjsua pjsua; 
     334typedef struct pjsua_call_info pjsua_call_info; 
     335 
     336 
     337enum pjsua_buddy_status 
     338{ 
     339    PJSUA_BUDDY_STATUS_UNKNOWN, 
     340    PJSUA_BUDDY_STATUS_ONLINE, 
     341    PJSUA_BUDDY_STATUS_OFFLINE, 
     342}; 
     343 
     344typedef enum pjsua_buddy_status pjsua_buddy_status; 
     345 
     346 
     347/** 
     348 * Buddy info. 
     349 */ 
     350struct 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 
     364typedef struct pjsua_buddy_info pjsua_buddy_info; 
     365 
     366 
     367/** 
     368 * Account info. 
     369 */ 
     370struct 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 
     382typedef struct pjsua_acc_info pjsua_acc_info; 
     383 
     384 
     385typedef int pjsua_player_id; 
     386typedef int pjsua_recorder_id; 
    422387 
    423388 
     
    434399 
    435400/** 
    436  * Test configuration. 
     401 * Validate configuration. 
    437402 */ 
    438403PJ_DECL(pj_status_t) pjsua_test_config(const pjsua_config *cfg, 
     
    442407 
    443408/** 
    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. 
    447411 */ 
    448412PJ_DECL(pj_status_t) pjsua_create(void); 
     
    470434PJ_DECL(pj_status_t) pjsua_start(void); 
    471435 
    472  
    473436/** 
    474437 * Destroy pjsua. 
    475438 */ 
    476439PJ_DECL(pj_status_t) pjsua_destroy(void); 
     440 
     441/** 
     442 * Get SIP endpoint instance. 
     443 * Only valid after pjsua_init(). 
     444 */ 
     445PJ_DECL(pjsip_endpoint*) pjsua_get_pjsip_endpt(void); 
     446 
     447/** 
     448 * Get media endpoint instance. 
     449 * Only valid after pjsua_init(). 
     450 */ 
     451PJ_DECL(pjmedia_endpt*) pjsua_get_pjmedia_endpt(void); 
     452 
     453/** 
     454 * Replace media transport. 
     455 */ 
     456PJ_DECL(pj_status_t) pjsua_set_call_media_transport(unsigned call_index, 
     457                                                    const pjmedia_sock_info *i, 
     458                                                    pjmedia_transport *tp); 
    477459 
    478460 
     
    482464 
    483465/** 
     466 * Get maximum number of calls configured in pjsua. 
     467 */ 
     468PJ_DECL(unsigned) pjsua_get_max_calls(void); 
     469 
     470/** 
     471 * Get current number of active calls. 
     472 */ 
     473PJ_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 */ 
     479PJ_DECL(pj_bool_t) pjsua_call_is_active(unsigned call_index); 
     480 
     481 
     482/** 
     483 * Check if call has a media session. 
     484 */ 
     485PJ_DECL(pj_bool_t) pjsua_call_has_media(unsigned call_index); 
     486 
     487 
     488/** 
     489 * Get call info. 
     490 */ 
     491PJ_DECL(pj_status_t) pjsua_get_call_info(unsigned call_index, 
     492                                         pjsua_call_info *info); 
     493 
     494 
     495/** 
     496 * Duplicate call info. 
     497 */ 
     498PJ_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/** 
    484504 * Make outgoing call. 
    485505 */ 
    486 PJ_DECL(pj_status_t) pjsua_make_call(int acc_index, 
    487                                      const char *cstr_dest_uri, 
     506PJ_DECL(pj_status_t) pjsua_make_call(unsigned acc_index, 
     507                                     const pj_str_t *dst_uri, 
    488508                                     int *p_call_index); 
    489509 
     
    515535 * Transfer call. 
    516536 */ 
    517 PJ_DECL(void) pjsua_call_xfer(int call_index, const char *dest); 
     537PJ_DECL(void) pjsua_call_xfer(unsigned call_index, const pj_str_t *dest); 
     538 
     539/** 
     540 * Dial DTMF. 
     541 */ 
     542PJ_DECL(pj_status_t) pjsua_call_dial_dtmf(unsigned call_index,  
     543                                          const pj_str_t *digits); 
    518544 
    519545 
     
    521547 * Send instant messaging inside INVITE session. 
    522548 */ 
    523 PJ_DECL(void) pjsua_call_send_im(int call_index, const char *text); 
     549PJ_DECL(void) pjsua_call_send_im(int call_index, const pj_str_t *text); 
    524550 
    525551 
     
    536562 
    537563/***************************************************************************** 
    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 */ 
     571PJ_DECL(unsigned) pjsua_get_acc_count(void); 
     572 
     573/** 
     574 * Get account info. 
     575 */ 
     576PJ_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 */ 
     585PJ_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 */ 
     593PJ_DECL(pj_status_t) pjsua_acc_set_online_status(unsigned acc_index, 
     594                                                 pj_bool_t is_online); 
     595 
    540596 
    541597/** 
     
    543599 * this will start unregistration process. 
    544600 */ 
    545 PJ_DECL(void) pjsua_regc_update(int acc_index, pj_bool_t renew); 
     601PJ_DECL(void) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew); 
    546602 
    547603 
     
    553609 
    554610/** 
     611 * Get buddy count. 
     612 */ 
     613PJ_DECL(unsigned) pjsua_get_buddy_count(void); 
     614 
     615 
     616/** 
     617 * Get buddy info. 
     618 */ 
     619PJ_DECL(pj_status_t) pjsua_buddy_get_info(unsigned buddy_index, 
     620                                          pjsua_buddy_info *info); 
     621 
     622/** 
     623 * Add new buddy. 
     624 */ 
     625PJ_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 */ 
     633PJ_DECL(pj_status_t) pjsua_buddy_subscribe_pres(unsigned buddy_index, 
     634                                                pj_bool_t monitor); 
     635 
     636 
     637/** 
    555638 * Refresh both presence client and server subscriptions. 
    556639 */ 
     
    577660 * Send IM outside dialog. 
    578661 */ 
    579 PJ_DECL(pj_status_t) pjsua_im_send(int acc_index, const char *dst_uri,  
    580                                    const char *text); 
     662PJ_DECL(pj_status_t) pjsua_im_send(int acc_index, const pj_str_t *dst_uri,  
     663                                   const pj_str_t *text); 
    581664 
    582665 
     
    584667 * Send typing indication outside dialog. 
    585668 */ 
    586 PJ_DECL(pj_status_t) pjsua_im_typing(int acc_index, const char *dst_uri,  
     669PJ_DECL(pj_status_t) pjsua_im_typing(int acc_index, const pj_str_t *dst_uri,  
    587670                                     pj_bool_t is_typing); 
    588671 
     672 
     673 
     674/***************************************************************************** 
     675 * Media. 
     676 */ 
     677 
     678/** 
     679 * Get maxinum number of conference ports. 
     680 */ 
     681PJ_DECL(unsigned) pjsua_conf_max_ports(void); 
     682 
     683 
     684/** 
     685 * Enum all conference ports. 
     686 */ 
     687PJ_DECL(pj_status_t) pjsua_conf_enum_ports(unsigned *count, 
     688                                           pjmedia_conf_port_info info[]); 
     689 
     690 
     691/** 
     692 * Connect conference port. 
     693 */ 
     694PJ_DECL(pj_status_t) pjsua_conf_connect(unsigned src_port, 
     695                                        unsigned dst_port); 
     696 
     697 
     698/** 
     699 * Connect conference port connection. 
     700 */ 
     701PJ_DECL(pj_status_t) pjsua_conf_disconnect(unsigned src_port, 
     702                                           unsigned dst_port); 
     703 
     704 
     705/** 
     706 * Create a file player. 
     707 */ 
     708PJ_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 */ 
     715PJ_DECL(unsigned) pjsua_player_get_conf_port(pjsua_player_id id); 
     716 
     717 
     718/** 
     719 * Set playback position. 
     720 */ 
     721PJ_DECL(pj_status_t) pjsua_player_set_pos(pjsua_player_id id, 
     722                                          pj_uint32_t samples); 
     723 
     724 
     725/** 
     726 * Destroy player. 
     727 */ 
     728PJ_DECL(pj_status_t) pjsua_player_destroy(pjsua_player_id id); 
     729 
     730 
     731 
     732/** 
     733 * Create a file recorder. 
     734 */ 
     735PJ_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 */ 
     742PJ_DECL(unsigned) pjsua_recorder_get_conf_port(pjsua_recorder_id id); 
     743 
     744 
     745/** 
     746 * Destroy recorder (will complete recording). 
     747 */ 
     748PJ_DECL(pj_status_t) pjsua_recorder_destroy(pjsua_recorder_id id); 
     749 
     750 
     751/** 
     752 * Enum sound devices. 
     753 */ 
     754PJ_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 */ 
     763PJ_DECL(pj_status_t) pjsua_set_snd_dev(int snd_capture_id, 
     764                                       int snd_player_id); 
    589765 
    590766 
     
    610786 
    611787/** 
     788 * Get pjsua running config. 
     789 */ 
     790PJ_DECL(const pjsua_config*) pjsua_get_config(void); 
     791 
     792 
     793/** 
    612794 * Dump settings. 
     795 * If cfg is NULL, it will dump current settings. 
    613796 */ 
    614797PJ_DECL(int) pjsua_dump_settings(const pjsua_config *cfg, 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r476 r482  
    126126 
    127127/** 
     128 * Get maximum number of calls configured in pjsua. 
     129 */ 
     130PJ_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 */ 
     139PJ_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 */ 
     148PJ_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 */ 
     159PJ_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 */ 
     169PJ_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 */ 
     228PJ_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/** 
    128246 * Make outgoing call. 
    129247 */ 
    130 PJ_DEF(pj_status_t) pjsua_make_call(int acc_index, 
    131                                     const char *cstr_dest_uri, 
     248PJ_DEF(pj_status_t) pjsua_make_call(unsigned acc_index, 
     249                                    const pj_str_t *dest_uri, 
    132250                                    int *p_call_index) 
    133251{ 
    134     pj_str_t dest_uri; 
    135252    pjsip_dialog *dlg = NULL; 
    136253    pjmedia_sdp_session *offer; 
     
    140257    pj_status_t status; 
    141258 
    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 
    145263 
    146264    /* Find free call slot. */ 
     
    165283                                   &pjsua.config.acc_config[acc_index].id, 
    166284                                   &pjsua.config.acc_config[acc_index].contact, 
    167                                    &dest_uri, &dest_uri, 
     285                                   dest_uri, dest_uri, 
    168286                                   &dlg); 
    169287    if (status != PJ_SUCCESS) { 
     
    656774    pjsip_generic_string_hdr *refer_to; 
    657775    char *uri; 
     776    pj_str_t tmp; 
    658777    struct pjsip_evsub_user xfer_cb; 
     778    pjsip_status_code code; 
    659779    pjsip_evsub *sub; 
    660780 
     
    674794    } 
    675795 
     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 
    676810    PJ_LOG(3,(THIS_FILE, "Call to %.*s is being transfered to %.*s", 
    677811              (int)inv->dlg->remote.info_str.slen, 
     
    693827 
    694828    /* Accept the REFER request, send 200 (OK). */ 
    695     pjsip_xfer_accept(sub, rdata, 200, NULL); 
     829    pjsip_xfer_accept(sub, rdata, code, NULL); 
    696830 
    697831    /* Create initial NOTIFY request */ 
     
    719853 
    720854    /* 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); 
    722857    if (status != PJ_SUCCESS) { 
    723858 
     
    10841219    { 
    10851220 
    1086         pjmedia_conf_connect_port( pjsua.mconf, pjsua.wav_slot,  
     1221        pjmedia_conf_connect_port( pjsua.mconf, pjsua.player[0].slot,  
    10871222                                   call->conf_slot, 0); 
    10881223 
     
    13081443 * Transfer call. 
    13091444 */ 
    1310 PJ_DEF(void) pjsua_call_xfer(int call_index, const char *dest) 
     1445PJ_DEF(void) pjsua_call_xfer(unsigned call_index, const pj_str_t *dest) 
    13111446{ 
    13121447    pjsip_evsub *sub; 
    13131448    pjsip_tx_data *tdata; 
    13141449    pjsua_call *call; 
    1315     pj_str_t tmp; 
    13161450    pj_status_t status; 
    13171451 
     
    13371471     * Create REFER request. 
    13381472     */ 
    1339     status = pjsip_xfer_initiate(sub, pj_cstr(&tmp, dest), &tdata); 
     1473    status = pjsip_xfer_initiate(sub, dest, &tdata); 
    13401474    if (status != PJ_SUCCESS) { 
    13411475        pjsua_perror(THIS_FILE, "Unable to create REFER request", status); 
     
    13581492 
    13591493/** 
     1494 * Dial DTMF. 
     1495 */ 
     1496PJ_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/** 
    13601513 * Send instant messaging inside INVITE session. 
    13611514 */ 
    1362 PJ_DECL(void) pjsua_call_send_im(int call_index, const char *str) 
     1515PJ_DECL(void) pjsua_call_send_im(int call_index, const pj_str_t *str) 
    13631516{ 
    13641517    pjsua_call *call; 
    13651518    const pj_str_t mime_text = pj_str("text"); 
    13661519    const pj_str_t mime_plain = pj_str("plain"); 
    1367     pj_str_t text; 
    13681520    pjsip_tx_data *tdata; 
    13691521    pj_status_t status; 
     
    13931545    /* Create "text/plain" message body. */ 
    13941546    tdata->msg->body = pjsip_msg_body_create( tdata->pool, &mime_text, 
    1395                                               &mime_plain,  
    1396                                               pj_cstr(&text, str)); 
     1547                                              &mime_plain, str); 
    13971548    if (tdata->msg->body == NULL) { 
    13981549        pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM); 
     
    15051656    return status; 
    15061657} 
     1658 
     1659/** 
     1660 * Replace media transport. 
     1661 */ 
     1662PJ_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  
    3535static pj_bool_t find_next_call(void) 
    3636{ 
    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)) { 
    4142            current_call = i; 
    4243            return PJ_TRUE; 
     
    4546 
    4647    for (i=0; i<current_call; ++i) { 
    47         if (pjsua.calls[i].inv != NULL) { 
     48        if (pjsua_call_is_active(i)) { 
    4849            current_call = i; 
    4950            return PJ_TRUE; 
     
    6162static pj_bool_t find_prev_call(void) 
    6263{ 
    63     int i; 
    64  
     64    int i, max; 
     65 
     66    max = pjsua_get_max_calls(); 
    6567    for (i=current_call-1; i>=0; --i) { 
    66         if (pjsua.calls[i].inv != NULL) { 
     68        if (pjsua_call_is_active(i)) { 
    6769            current_call = i; 
    6870            return PJ_TRUE; 
     
    7072    } 
    7173 
    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)) { 
    7476            current_call = i; 
    7577            return PJ_TRUE; 
     
    8890static void console_on_call_state(int call_index, pjsip_event *e) 
    8991{ 
    90     pjsua_call *call = &pjsua.calls[call_index]; 
     92    pjsua_call_info call_info; 
    9193 
    9294    PJ_UNUSED_ARG(e); 
    9395 
    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) { 
    9599 
    96100        PJ_LOG(3,(THIS_FILE, "Call %d is DISCONNECTED [reason=%d (%s)]",  
    97101                  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) { 
    103106            find_next_call(); 
    104107        } 
     
    108111        PJ_LOG(3,(THIS_FILE, "Call %d state changed to %s",  
    109112                  call_index, 
    110                   pjsua_inv_state_names[call->inv->state])); 
    111  
    112         if (call && 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; 
    114117 
    115118    } 
     
    124127 
    125128    // Log already written. 
     129} 
     130 
     131 
     132/** 
     133 * Notify UI on buddy state changed. 
     134 */ 
     135static 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)); 
    126145} 
    127146 
     
    163182static void print_buddy_list(void) 
    164183{ 
    165     int i; 
     184    int i, count; 
    166185 
    167186    puts("Buddy list:"); 
    168187 
    169     if (pjsua.buddy_cnt == 0) 
     188    count = pjsua_get_buddy_count(); 
     189 
     190    if (count == 0) 
    170191        puts(" -none-"); 
    171192    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); 
    187206        } 
    188207    } 
     
    196215static void print_acc_status(int acc_index) 
    197216{ 
    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-"); 
    221224 
    222225    } 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); 
    228237    printf("     Online status: %s\n",  
    229            (pjsua.acc[acc_index].online_status ? "Online" : "Invisible")); 
     238           (info.online_status ? "Online" : "Invisible")); 
    230239} 
    231240 
     
    239248    printf(">>>>\n"); 
    240249 
    241     for (i=0; i<(int)pjsua.config.acc_cnt; ++i) 
     250    for (i=0; i<(int)pjsua_get_acc_count(); ++i) 
    242251        print_acc_status(i); 
    243252 
     
    312321           "  URL        An URL\n" 
    313322           "  <Enter>    Empty input (or 'q') to cancel\n" 
    314            , pjsua.buddy_cnt, pjsua.buddy_cnt); 
     323           , pjsua_get_buddy_count(), pjsua_get_buddy_count()); 
    315324    printf("%s: ", title); 
    316325 
     
    350359        result->nb_result = atoi(buf); 
    351360 
    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        { 
    353364            return; 
    354365        } 
     
    380391 
    381392    count = PJ_ARRAY_SIZE(info); 
    382     pjmedia_conf_get_ports_info(pjsua.mconf, &count, info); 
     393    pjsua_conf_enum_ports(&count, info); 
    383394    for (i=0; i<count; ++i) { 
    384395        char txlist[PJSUA_MAX_CALLS*4+10]; 
     
    414425    int i, count; 
    415426    char *uri; 
     427    pj_str_t tmp; 
    416428    struct input_result result; 
     429    pjsua_call_info call_info; 
     430    pjsua_acc_info acc_info; 
    417431 
    418432 
    419433    /* 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); 
    422437    } 
    423438 
     
    435450        case 'm': 
    436451            /* 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()); 
    438453             
    439454            uri = NULL; 
     
    445460                    continue; 
    446461                } 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; 
    448465                } 
    449466 
     
    452469            } 
    453470             
    454             pjsua_make_call( current_acc, uri, NULL); 
     471            tmp = pj_str(uri); 
     472            pjsua_make_call( current_acc, &tmp, NULL); 
    455473            break; 
    456474 
    457475        case 'M': 
    458476            /* 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()); 
    460478             
    461479            if (!simple_input("Number of calls", menuin, sizeof(menuin))) 
     
    468486            ui_input_url("Make call", buf, sizeof(buf), &result); 
    469487            if (result.nb_result != NO_NB) { 
     488                pjsua_buddy_info binfo; 
    470489                if (result.nb_result == -1 || result.nb_result == 0) { 
    471490                    puts("You can't do that with make call!"); 
    472491                    continue; 
    473492                } 
    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; 
    475495            } else { 
    476496                uri =  result.uri_result; 
     
    479499            for (i=0; i<atoi(menuin); ++i) { 
    480500                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); 
    483504                if (status != PJ_SUCCESS) 
    484505                    break; 
     
    508529 
    509530                } 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; 
    511534                } 
    512535 
     
    519542            if (i != -1) 
    520543                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            } 
    523548 
    524549            /* Input the IM . */ 
     
    530555                if (i != -1) 
    531556                    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                } 
    534561                continue; 
    535562            } 
     563 
     564            tmp = pj_str(text); 
    536565 
    537566            /* Send the IM */ 
    538567            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            } 
    542573 
    543574            break; 
     
    545576        case 'a': 
    546577 
     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 
    547587            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) 
    550591            { 
    551592                puts("No pending incoming call"); 
     
    609650 
    610651            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)); 
    624657 
    625658            } else { 
     
    677710                    if (result.nb_result == -1 || result.nb_result == 0) 
    678711                        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); 
    680715                        pjsua_call_xfer( current_call, 
    681                                          pjsua.buddies[result.nb_result-1].uri.ptr); 
     716                                         &binfo.uri); 
     717                    } 
    682718 
    683719                } 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); 
    685723                } 
    686724            } 
     
    695733                PJ_LOG(3,(THIS_FILE, "No current call")); 
    696734 
    697             } else if (pjsua.calls[current_call].session == NULL) { 
     735            } else if (!pjsua_call_has_media(current_call)) { 
    698736 
    699737                PJ_LOG(3,(THIS_FILE, "Media is not established yet!")); 
     
    716754 
    717755                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); 
    720757                if (status != PJ_SUCCESS) { 
    721758                    pjsua_perror(THIS_FILE, "Unable to send DTMF", status); 
     
    734771            if (result.nb_result != NO_NB) { 
    735772                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'); 
    739777                } else if (result.nb_result == 0) { 
    740778                    puts("Sorry, can only subscribe to buddy's presence, " 
    741779                         "not from existing call"); 
    742780                } else { 
    743                     pjsua.buddies[result.nb_result-1].monitor = (menuin[0]=='s'); 
     781                    pjsua_buddy_subscribe_pres(result.nb_result-1, (menuin[0]=='s')); 
    744782                } 
    745783 
     
    759797                 * Re-Register. 
    760798                 */ 
    761                 pjsua_regc_update(current_acc, PJ_TRUE); 
     799                pjsua_acc_set_registration(current_acc, PJ_TRUE); 
    762800                break; 
    763801            case 'u': 
     
    765803                 * Unregister 
    766804                 */ 
    767                 pjsua_regc_update(current_acc, PJ_FALSE); 
     805                pjsua_acc_set_registration(current_acc, PJ_FALSE); 
    768806                break; 
    769807            } 
     
    771809             
    772810        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); 
    775814            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")); 
    778817            pjsua_pres_refresh(current_acc); 
    779818            break; 
     
    807846 
    808847                    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)); 
    813850                    } 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)); 
    817853                    } 
    818854                    if (status == PJ_SUCCESS) { 
     
    831867                int len; 
    832868 
    833                 len = pjsua_dump_settings(&pjsua.config, settings,  
     869                len = pjsua_dump_settings(NULL, settings,  
    834870                                          sizeof(settings)); 
    835871                if (len < 1) 
     
    947983    /* Write to both stdout and file. */ 
    948984 
    949     if (level <= (int)pjsua.config.app_log_level) 
     985    if (level <= (int)pjsua_get_config()->app_log_level) 
    950986        pj_log_write(level, buffer, len); 
    951987 
     
    10101046{ 
    10111047    &console_on_call_state, 
     1048    NULL,   /* default accept transfer */ 
    10121049    &console_on_reg_state, 
     1050    &console_on_buddy_state, 
    10131051    &console_on_pager, 
    10141052    &console_on_typing, 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r476 r482  
    8585        cfg->acc_config[i].reg_timeout = 55; 
    8686    } 
     87 
    8788} 
    8889 
     
    526527    int i; 
    527528    unsigned options; 
    528     unsigned clock_rate; 
    529     unsigned samples_per_frame; 
    530529    pj_str_t codec_id; 
    531530    pj_status_t status; 
     
    604603 
    605604    /* Init options for conference bridge. */ 
    606     options = 0; 
     605    options = PJMEDIA_CONF_NO_DEVICE; 
    607606 
    608607    /* Calculate maximum number of ports, if it's not specified */ 
     
    612611 
    613612    /* 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; 
    616615    status = pjmedia_conf_create(pjsua.pool,  
    617616                                 pjsua.config.conf_ports,  
    618                                  clock_rate,  
     617                                 pjsua.clock_rate,  
    619618                                 1, /* mono */ 
    620                                  samples_per_frame,  
     619                                 pjsua.samples_per_frame,  
    621620                                 16,  
    622621                                 options, 
     
    629628    } 
    630629 
     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 
    631675    /* Create WAV file player if required: */ 
    632676 
    633677    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); 
    641680        if (status != PJ_SUCCESS) { 
    642             pjsua_perror(THIS_FILE,  
    643                          "Error playing media file",  
     681            pjsua_perror(THIS_FILE, "Unable to create file player",  
    644682                         status); 
    645683            return status; 
    646684        } 
    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         } 
    660685    } 
    661686 
    662687 
    663688    return PJ_SUCCESS; 
     689} 
     690 
     691 
     692/* 
     693 * Copy account configuration. 
     694 */ 
     695static 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    } 
    664716} 
    665717 
     
    692744        pjsua_acc_config *dst_acc = &dst->acc_config[i]; 
    693745        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); 
    711747    } 
    712748 
     
    748784    } 
    749785 
     786    /* Init buddies array */ 
     787    for (i=0; i<PJ_ARRAY_SIZE(pjsua.buddies); ++i) { 
     788        pjsua.buddies[i].index = i; 
     789    } 
     790 
    750791    /* Copy configuration */ 
    751792    copy_config(pjsua.pool, &pjsua.config, cfg); 
     
    757798    if (pjsua_test_config(&pjsua.config, errmsg, sizeof(errmsg))) { 
    758799        PJ_LOG(1,(THIS_FILE, "Error in configuration: %s", errmsg)); 
    759         return -1; 
     800        status = -1; 
     801        goto on_error; 
    760802    } 
    761803 
     
    774816                                      &pjsua.sip_sock_name); 
    775817        if (status != PJ_SUCCESS) 
    776             return status; 
     818            goto on_error; 
    777819     
    778820        pj_strdup2_with_null(pjsua.pool, &pjsua.config.sip_host, 
     
    786828            PJ_LOG(1,(THIS_FILE,  
    787829                      "Error: sip_host and sip_port must be specified")); 
    788             return PJ_EINVAL; 
     830            status = PJ_EINVAL; 
     831            goto on_error; 
    789832        } 
    790833 
     
    796839    status = init_media(); 
    797840    if (status != PJ_SUCCESS) 
    798         return status; 
     841        goto on_error; 
    799842 
    800843 
     
    805848            unsigned j; 
    806849            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); 
    808852            } 
    809             return status; 
     853            goto on_error; 
    810854        } 
    811855        status = pjmedia_transport_udp_attach(pjsua.med_endpt, NULL, 
     
    897941 
    898942on_error: 
    899     pj_caching_pool_destroy(&pjsua.cp); 
     943    pjsua_destroy(); 
    900944    return status; 
    901945} 
     
    9641008 
    9651009 
     1010/* 
     1011 * Init account 
     1012 */ 
     1013static 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 */ 
     1123PJ_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 
    9661148 
    9671149/* 
     
    9721154{ 
    9731155    int i;  /* Must be signed */ 
     1156    unsigned count; 
    9741157    pj_status_t status = PJ_SUCCESS; 
    9751158 
     
    9951178            pjsua_perror(THIS_FILE, "Unable to start UDP transport",  
    9961179                         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. 
    10031185     */ 
    10041186    { 
    10051187        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; 
    10091189 
    10101190        tmp.ptr = buf; 
     
    10121192                                   pjsua.config.sip_host.ptr, 
    10131193                                   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        } 
    10171205    } 
    10181206     
     
    10201208    /* Initialize accounts: */ 
    10211209    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    } 
    11261216 
    11271217 
     
    11381228                pj_thread_destroy(pjsua.threads[i]); 
    11391229            } 
    1140             return status; 
     1230            goto on_error; 
    11411231        } 
    11421232    } 
     
    11481238        status = pjsua_regc_init(i); 
    11491239        if (status != PJ_SUCCESS) 
    1150             return status; 
     1240            goto on_error; 
    11511241 
    11521242        /* Perform registration, if required. */ 
    11531243        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 
    11701257 
    11711258 
    11721259    PJ_LOG(3,(THIS_FILE, "PJSUA version %s started", PJ_VERSION)); 
    11731260    return PJ_SUCCESS; 
     1261 
     1262on_error: 
     1263    pjsua_destroy(); 
     1264    return status; 
    11741265} 
    11751266 
     
    11901281} 
    11911282 
     1283/** 
     1284 * Get maxinum number of conference ports. 
     1285 */ 
     1286PJ_DEF(unsigned) pjsua_conf_max_ports(void) 
     1287{ 
     1288    return pjsua.config.conf_ports; 
     1289} 
     1290 
     1291 
     1292/** 
     1293 * Enum all conference ports. 
     1294 */ 
     1295PJ_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 */ 
     1307PJ_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 */ 
     1317PJ_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 */ 
     1328PJ_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 */ 
     1371PJ_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 */ 
     1381PJ_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 */ 
     1394PJ_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 */ 
     1412PJ_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 */ 
     1455PJ_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 */ 
     1465PJ_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 */ 
     1482PJ_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 */ 
     1505PJ_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 
    11921514/* 
    11931515 * Destroy pjsua. 
     
    12091531    for (i=0; i<(int)pjsua.config.acc_cnt; ++i) { 
    12101532        if (pjsua.acc[i].regc) { 
    1211             pjsua_regc_update(i, 0); 
     1533            pjsua_acc_set_registration(i, PJ_FALSE); 
    12121534        } 
    12131535    } 
     
    12251547 
    12261548    /* 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    } 
    12551587 
    12561588 
    12571589    /* 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        } 
    12601595    } 
    12611596 
    12621597    /* 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    } 
    12651621 
    12661622    /* 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    } 
    12701627 
    12711628    /* Destroy caching pool. */ 
    1272  
    12731629    pj_caching_pool_destroy(&pjsua.cp); 
    12741630 
     
    12791635} 
    12801636 
     1637 
     1638/** 
     1639 * Get SIP endpoint instance. 
     1640 * Only valid after pjsua_init(). 
     1641 */ 
     1642PJ_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 */ 
     1651PJ_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  
    1919#include <pjsua-lib/pjsua.h> 
    2020#include <pj/log.h> 
     21#include "pjsua_imp.h" 
    2122 
    2223/* 
     
    272273 * Send IM outside dialog. 
    273274 */ 
    274 PJ_DEF(pj_status_t) pjsua_im_send(int acc_index, const char *dst_uri,  
    275                                   const char *str) 
     275PJ_DEF(pj_status_t) pjsua_im_send(int acc_index, const pj_str_t *dst_uri,  
     276                                  const pj_str_t *str) 
    276277{ 
    277278    pjsip_tx_data *tdata; 
     
    280281    const pj_str_t mime_plain = pj_str("plain"); 
    281282    pj_str_t *text; 
    282     const pj_str_t dst = pj_str((char*)dst_uri); 
    283283    pj_status_t status; 
    284284 
    285285    /* Create request. */ 
    286286    status = pjsip_endpt_create_request(pjsua.endpt, &pjsip_message_method, 
    287                                         &dst,  
     287                                        dst_uri,  
    288288                                        &pjsua.config.acc_config[acc_index].id, 
    289                                         &dst, NULL, NULL, -1, NULL, &tdata); 
     289                                        dst_uri, NULL, NULL, -1, NULL, &tdata); 
    290290    if (status != PJ_SUCCESS) { 
    291291        pjsua_perror(THIS_FILE, "Unable to create request", status); 
     
    308308     */ 
    309309    text = pj_pool_alloc(tdata->pool, sizeof(pj_str_t)); 
    310     pj_strdup2_with_null(tdata->pool, text, str); 
     310    pj_strdup_with_null(tdata->pool, text, str); 
    311311 
    312312    /* Add message body */ 
     
    334334 * Send typing indication outside dialog. 
    335335 */ 
    336 PJ_DEF(pj_status_t) pjsua_im_typing(int acc_index, const char *dst_uri,  
     336PJ_DEF(pj_status_t) pjsua_im_typing(int acc_index, const pj_str_t *dst_uri,  
    337337                                    pj_bool_t is_typing) 
    338338{ 
    339     const pj_str_t dst = pj_str((char*)dst_uri); 
    340339    pjsip_tx_data *tdata; 
    341340    pj_status_t status; 
     
    343342    /* Create request. */ 
    344343    status = pjsip_endpt_create_request( pjsua.endpt, &pjsip_message_method, 
    345                                          &dst,  
     344                                         dst_uri,  
    346345                                         &pjsua.config.acc_config[acc_index].id, 
    347                                          &dst, NULL, NULL, -1, NULL, &tdata); 
     346                                         dst_uri, NULL, NULL, -1, NULL, &tdata); 
    348347    if (status != PJ_SUCCESS) { 
    349348        pjsua_perror(THIS_FILE, "Unable to create request", status); 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_imp.h

    r476 r482  
    2222 
    2323 
     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 */ 
     31struct 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 
     51typedef struct pjsua_call pjsua_call; 
     52 
     53 
     54/** 
     55 * Buddy data. 
     56 */ 
     57struct 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 
     70typedef struct pjsua_buddy pjsua_buddy; 
     71 
     72 
     73/** 
     74 * Server presence subscription list head. 
     75 */ 
     76struct pjsua_srv_pres 
     77{ 
     78    PJ_DECL_LIST_MEMBER(struct pjsua_srv_pres); 
     79    pjsip_evsub     *sub; 
     80    char            *remote; 
     81}; 
     82 
     83typedef struct pjsua_srv_pres pjsua_srv_pres; 
     84 
     85 
     86 
     87/** 
     88 * Account 
     89 */ 
     90struct 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 */ 
     113typedef struct pjsua_acc pjsua_acc; 
     114 
     115 
     116/* PJSUA application variables. */ 
     117struct 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. */ 
     182extern struct pjsua pjsua; 
     183 
     184 
     185 
    24186/** 
    25187 * Find account for incoming request. 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c

    r476 r482  
    236236    if (buddy) { 
    237237        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,  
    240241                  pjsip_evsub_get_state_name(sub))); 
    241242 
     
    245246            pjsip_evsub_set_mod_data(sub, pjsua.mod.id, NULL); 
    246247        } 
     248 
     249        /* Call callback */ 
     250        if (pjsua.cb.on_buddy_state) 
     251            (*pjsua.cb.on_buddy_state)(buddy->index); 
    247252    } 
    248253} 
     
    262267        /* Update our info. */ 
    263268        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         } 
    273269    } 
    274270 
     
    321317                                   &acc_config->id, 
    322318                                   &acc_config->contact, 
    323                                    &pjsua.buddies[index].uri, 
     319                                   &pjsua.config.buddy_uri[index], 
    324320                                   NULL, &dlg); 
    325321    if (status != PJ_SUCCESS) { 
     
    401397static void refresh_client_subscription(void) 
    402398{ 
    403     int i; 
    404  
    405     for (i=0; i<pjsua.buddy_cnt; ++i) { 
     399    unsigned i; 
     400 
     401    for (i=0; i<pjsua.config.buddy_cnt; ++i) { 
    406402 
    407403        if (pjsua.buddies[i].monitor && !pjsua.buddies[i].sub) { 
     
    433429 
    434430/* 
     431 * Get buddy count. 
     432 */ 
     433PJ_DEF(unsigned) pjsua_get_buddy_count(void) 
     434{ 
     435    return pjsua.config.buddy_cnt; 
     436} 
     437 
     438 
     439/** 
     440 * Get buddy info. 
     441 */ 
     442PJ_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 */ 
     481PJ_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 
     527PJ_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 
     540PJ_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/* 
    435550 * Refresh presence 
    436551 */ 
     
    447562void pjsua_pres_shutdown(void) 
    448563{ 
    449     int acc_index; 
    450     int i; 
     564    unsigned acc_index; 
     565    unsigned i; 
    451566 
    452567    for (acc_index=0; acc_index<(int)pjsua.config.acc_cnt; ++acc_index) { 
     
    454569    } 
    455570 
    456     for (i=0; i<pjsua.buddy_cnt; ++i) { 
     571    for (i=0; i<pjsua.config.buddy_cnt; ++i) { 
    457572        pjsua.buddies[i].monitor = 0; 
    458573    } 
     
    468583void pjsua_pres_dump(pj_bool_t detail) 
    469584{ 
    470     int acc_index; 
    471     int i; 
     585    unsigned acc_index; 
     586    unsigned i; 
    472587 
    473588 
     
    498613        count = 0; 
    499614 
    500         for (i=0; i<pjsua.buddy_cnt; ++i) { 
     615        for (i=0; i<pjsua.config.buddy_cnt; ++i) { 
    501616            if (pjsua.buddies[i].sub) { 
    502617                ++count; 
     
    545660    PJ_LOG(3,(THIS_FILE, "Dumping pjsua client subscriptions:")); 
    546661 
    547     if (pjsua.buddy_cnt == 0) { 
     662    if (pjsua.config.buddy_cnt == 0) { 
    548663 
    549664        PJ_LOG(3,(THIS_FILE, "  - no buddy list - ")); 
    550665 
    551666    } else { 
    552         for (i=0; i<pjsua.buddy_cnt; ++i) { 
     667        for (i=0; i<pjsua.config.buddy_cnt; ++i) { 
    553668 
    554669            if (pjsua.buddies[i].sub) { 
    555                 PJ_LOG(3,(THIS_FILE, "  %10s %s", 
     670                PJ_LOG(3,(THIS_FILE, "  %10s %.*s", 
    556671                          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)); 
    558674            } else { 
    559                 PJ_LOG(3,(THIS_FILE, "  %10s %s", 
     675                PJ_LOG(3,(THIS_FILE, "  %10s %.*s", 
    560676                          "(null)", 
    561                           pjsua.buddies[i].uri.ptr)); 
     677                          (int)pjsua.config.buddy_uri[i].slen, 
     678                          pjsua.config.buddy_uri[i].ptr)); 
    562679            } 
    563680        } 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_reg.c

    r476 r482  
    1818 */ 
    1919#include <pjsua-lib/pjsua.h> 
     20#include "pjsua_imp.h" 
    2021 
    2122 
     
    8384 
    8485 
     86/** 
     87 * Get number of accounts. 
     88 */ 
     89PJ_DEF(unsigned) pjsua_get_acc_count(void) 
     90{ 
     91    return pjsua.config.acc_cnt; 
     92} 
     93 
     94 
     95/** 
     96 * Get account info. 
     97 */ 
     98PJ_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, &regc_info); 
     125        info->expires = regc_info.next_reg; 
     126    } 
     127 
     128    return PJ_SUCCESS; 
     129} 
     130 
     131 
    85132/* 
    86133 * Update registration. If renew is false, then unregistration will be performed. 
    87134 */ 
    88 PJ_DECL(void) pjsua_regc_update(int acc_index, pj_bool_t renew) 
     135PJ_DECL(void) pjsua_acc_set_registration(unsigned acc_index, pj_bool_t renew) 
    89136{ 
    90137    pj_status_t status = 0; 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_settings.c

    r476 r482  
    1919#include <pjsua-lib/pjsua.h> 
    2020#include <stdio.h> 
     21#include "pjsua_imp.h" 
     22 
    2123 
    2224/* 
     
    10081010    PJ_UNUSED_ARG(max); 
    10091011 
     1012    if (config == NULL) 
     1013        config = &pjsua.config; 
     1014 
    10101015    cfg.ptr = buf; 
    10111016    cfg.slen = 0; 
     
    12111216    return PJ_SUCCESS; 
    12121217} 
     1218 
     1219/** 
     1220 * Get pjsua running config. 
     1221 */ 
     1222PJ_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.