--- a/pjsip/include/pjsua-lib/pjsua.h +++ b/pjsip/include/pjsua-lib/pjsua.h @@ -1543,6 +1543,8 @@ PJ_DECL(pjmedia_endpt*) pjsua_get_pjmedi PJ_DECL(pj_pool_factory*) pjsua_get_pool_factory(void); +PJ_DECL(pj_status_t) pjsua_add_snd_port(int id, pjsua_conf_port_id *p_id); + /***************************************************************************** * Utilities. --- a/pjsip/include/pjsua-lib/pjsua_internal.h +++ b/pjsip/include/pjsua-lib/pjsua_internal.h @@ -261,6 +261,8 @@ typedef struct pjsua_stun_resolve } pjsua_stun_resolve; +#define MAX_PORT 2 + /** * Global pjsua application data. */ @@ -336,7 +338,7 @@ struct pjsua_data pj_bool_t aud_open_cnt;/**< How many # device is opened */ pj_bool_t no_snd; /**< No sound (app will manage it) */ pj_pool_t *snd_pool; /**< Sound's private pool. */ - pjmedia_snd_port *snd_port; /**< Sound port. */ + pjmedia_snd_port *snd_port[MAX_PORT]; /**< Sound port. */ pj_timer_entry snd_idle_timer;/**< Sound device idle timer. */ pjmedia_master_port *null_snd; /**< Master port for null sound. */ pjmedia_port *null_port; /**< Null port. */ --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -588,7 +588,7 @@ static void check_snd_dev_idle() * It is idle when there is no port connection in the bridge and * there is no active call. */ - if ((pjsua_var.snd_port!=NULL || pjsua_var.null_snd!=NULL) && + if ((pjsua_var.snd_port[0]!=NULL || pjsua_var.null_snd!=NULL) && pjsua_var.snd_idle_timer.id == PJ_FALSE && pjmedia_conf_get_connect_count(pjsua_var.mconf) == 0 && call_cnt == 0 && @@ -2008,7 +2008,7 @@ PJ_DEF(pj_status_t) pjsua_conf_connect( pj_assert(status == PJ_SUCCESS); /* Check if sound device is instantiated. */ - need_reopen = (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL && + need_reopen = (pjsua_var.snd_port[0]==NULL && pjsua_var.null_snd==NULL && !pjsua_var.no_snd); /* Check if sound device need to reopen because it needs to modify @@ -2072,7 +2072,7 @@ PJ_DEF(pj_status_t) pjsua_conf_connect( /* The bridge version */ /* Create sound port if none is instantiated */ - if (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL && + if (pjsua_var.snd_port[0]==NULL && pjsua_var.null_snd==NULL && !pjsua_var.no_snd) { pj_status_t status; @@ -2686,9 +2686,9 @@ static pj_status_t update_initial_aud_pa pjmedia_aud_param param; pj_status_t status; - PJ_ASSERT_RETURN(pjsua_var.snd_port != NULL, PJ_EBUG); + PJ_ASSERT_RETURN(pjsua_var.snd_port[0] != NULL, PJ_EBUG); - strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); + strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]); status = pjmedia_aud_stream_get_param(strm, ¶m); if (status != PJ_SUCCESS) { @@ -2754,7 +2754,7 @@ static pj_status_t open_snd_dev(pjmedia_ 1000 / param->base.clock_rate)); status = pjmedia_snd_port_create2( pjsua_var.snd_pool, - param, &pjsua_var.snd_port); + param, &pjsua_var.snd_port[0]); if (status != PJ_SUCCESS) return status; @@ -2812,13 +2812,13 @@ static pj_status_t open_snd_dev(pjmedia_ } /* Connect sound port to the bridge */ - status = pjmedia_snd_port_connect(pjsua_var.snd_port, + status = pjmedia_snd_port_connect(pjsua_var.snd_port[0], conf_port ); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to connect conference port to " "sound device", status); - pjmedia_snd_port_destroy(pjsua_var.snd_port); - pjsua_var.snd_port = NULL; + pjmedia_snd_port_destroy(pjsua_var.snd_port[0]); + pjsua_var.snd_port[0] = NULL; return status; } @@ -2833,7 +2833,7 @@ static pj_status_t open_snd_dev(pjmedia_ pjmedia_aud_param si; pj_str_t tmp; - strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); + strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]); status = pjmedia_aud_stream_get_param(strm, &si); if (status == PJ_SUCCESS) status = pjmedia_aud_dev_get_info(si.rec_id, &rec_info); @@ -2876,12 +2876,12 @@ static pj_status_t open_snd_dev(pjmedia_ static void close_snd_dev(void) { /* Close sound device */ - if (pjsua_var.snd_port) { + if (pjsua_var.snd_port[0]) { pjmedia_aud_dev_info cap_info, play_info; pjmedia_aud_stream *strm; pjmedia_aud_param param; - strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); + strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]); pjmedia_aud_stream_get_param(strm, ¶m); if (pjmedia_aud_dev_get_info(param.rec_id, &cap_info) != PJ_SUCCESS) @@ -2893,9 +2893,9 @@ static void close_snd_dev(void) "%s sound capture device", play_info.name, cap_info.name)); - pjmedia_snd_port_disconnect(pjsua_var.snd_port); - pjmedia_snd_port_destroy(pjsua_var.snd_port); - pjsua_var.snd_port = NULL; + pjmedia_snd_port_disconnect(pjsua_var.snd_port[0]); + pjmedia_snd_port_destroy(pjsua_var.snd_port[0]); + pjsua_var.snd_port[0] = NULL; } /* Close null sound device */ @@ -2984,6 +2984,35 @@ PJ_DEF(pj_status_t) pjsua_set_snd_dev( i return PJ_SUCCESS; } +PJ_DEF(pj_status_t) pjsua_add_snd_port(int id, pjsua_conf_port_id *p_id) +{ + unsigned alt_cr_cnt = 1; + unsigned alt_cr = 0; + pj_status_t status = -1; + pjmedia_snd_port_param param; + unsigned samples_per_frame; + pjmedia_port *port; + const pj_str_t name = pj_str("tapi2"); + alt_cr = pjsua_var.media_cfg.clock_rate; + samples_per_frame = alt_cr * + pjsua_var.media_cfg.audio_frame_ptime * + pjsua_var.media_cfg.channel_count / 1000; + status = create_aud_param(¶m.base, + pjsua_var.play_dev, + pjsua_var.cap_dev, + alt_cr, + pjsua_var.media_cfg.channel_count, + samples_per_frame, 16); + if (status != PJ_SUCCESS) + return status; + param.base.rec_id = id; + param.base.play_id = id; + param.options = 0; + status = pjmedia_snd_port_create2(pjsua_var.snd_pool, + ¶m, &pjsua_var.snd_port[id]); + return PJ_SUCCESS; +} + /* * Get currently active sound devices. If sound devices has not been created @@ -3088,7 +3117,7 @@ PJ_DEF(pj_status_t) pjsua_set_ec(unsigne pjsua_var.media_cfg.ec_options = options; if (pjsua_var.snd_port) - status = pjmedia_snd_port_set_ec(pjsua_var.snd_port, pjsua_var.pool, + status = pjmedia_snd_port_set_ec(pjsua_var.snd_port[0], pjsua_var.pool, tail_ms, options); PJSUA_UNLOCK(); @@ -3111,7 +3140,7 @@ PJ_DEF(pj_status_t) pjsua_get_ec_tail(un */ PJ_DEF(pj_bool_t) pjsua_snd_is_active(void) { - return pjsua_var.snd_port != NULL; + return pjsua_var.snd_port[0] != NULL; } @@ -3135,7 +3164,7 @@ PJ_DEF(pj_status_t) pjsua_snd_set_settin if (pjsua_snd_is_active()) { pjmedia_aud_stream *strm; - strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); + strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]); status = pjmedia_aud_stream_set_cap(strm, cap, pval); } else { status = PJ_SUCCESS; @@ -3181,7 +3210,7 @@ PJ_DEF(pj_status_t) pjsua_snd_get_settin /* Sound is active, retrieve from device directly */ pjmedia_aud_stream *strm; - strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); + strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]); status = pjmedia_aud_stream_get_cap(strm, cap, pval); } else { /* Otherwise retrieve from internal param */