From fbbfd915b0225c657920a6696f460a687f28cc6b Mon Sep 17 00:00:00 2001 From: Riza Sulistyo Date: Mon, 4 Apr 2016 01:44:10 +0000 Subject: Re #1908: Implement new API to open speaker only in pjsua/pjsua2. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5273 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip-apps/src/swig/symbols.i | 2 + pjsip-apps/src/swig/symbols.lst | 2 +- pjsip/include/pjsua-lib/pjsua.h | 65 ++++++++++++++++++++++++++ pjsip/include/pjsua-lib/pjsua_internal.h | 1 + pjsip/include/pjsua2/media.hpp | 17 ++++++- pjsip/src/pjsua-lib/pjsua_aud.c | 79 +++++++++++++++++++++++++++----- pjsip/src/pjsua2/media.cpp | 37 +++++++++++++-- 7 files changed, 184 insertions(+), 19 deletions(-) diff --git a/pjsip-apps/src/swig/symbols.i b/pjsip-apps/src/swig/symbols.i index 4b4e53fe..feb4f18b 100644 --- a/pjsip-apps/src/swig/symbols.i +++ b/pjsip-apps/src/swig/symbols.i @@ -165,3 +165,5 @@ typedef enum pjsua_call_flag {PJSUA_CALL_UNHOLD = 1, PJSUA_CALL_UPDATE_CONTACT = typedef enum pjsua_create_media_transport_flag {PJSUA_MED_TP_CLOSE_MEMBER = 1} pjsua_create_media_transport_flag; +typedef enum pjsua_snd_dev_mode {PJSUA_SND_DEV_SPEAKER_ONLY = 1, PJSUA_SND_DEV_NO_IMMEDIATE_OPEN = 2} pjsua_snd_dev_mode; + diff --git a/pjsip-apps/src/swig/symbols.lst b/pjsip-apps/src/swig/symbols.lst index 35ba8b02..62b0e1ff 100644 --- a/pjsip-apps/src/swig/symbols.lst +++ b/pjsip-apps/src/swig/symbols.lst @@ -33,4 +33,4 @@ pjsip-simple/evsub.h pjsip_evsub_state pjsip-ua/sip_inv.h pjsip_inv_state -pjsua-lib/pjsua.h pjsua_invalid_id_const_ pjsua_state pjsua_stun_use pjsua_call_hold_type pjsua_acc_id pjsua_destroy_flag pjsua_100rel_use pjsua_sip_timer_use pjsua_ipv6_use pjsua_buddy_status pjsua_call_media_status pjsua_vid_win_id pjsua_call_id pjsua_med_tp_st pjsua_call_vid_strm_op pjsua_vid_req_keyframe_method pjsua_call_flag pjsua_create_media_transport_flag +pjsua-lib/pjsua.h pjsua_invalid_id_const_ pjsua_state pjsua_stun_use pjsua_call_hold_type pjsua_acc_id pjsua_destroy_flag pjsua_100rel_use pjsua_sip_timer_use pjsua_ipv6_use pjsua_buddy_status pjsua_call_media_status pjsua_vid_win_id pjsua_call_id pjsua_med_tp_st pjsua_call_vid_strm_op pjsua_vid_req_keyframe_method pjsua_call_flag pjsua_create_media_transport_flag pjsua_snd_dev_mode diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h index 6b6b5569..4887a97e 100644 --- a/pjsip/include/pjsua-lib/pjsua.h +++ b/pjsip/include/pjsua-lib/pjsua.h @@ -5997,6 +5997,62 @@ typedef struct pjsua_media_transport } pjsua_media_transport; +/** + * This enumeration specifies the sound device mode. + */ +typedef enum pjsua_snd_dev_mode +{ + /** + * Open sound device without mic (speaker only). + */ + PJSUA_SND_DEV_SPEAKER_ONLY = 1, + + /** + * Do not open sound device, after setting the sound device. + */ + PJSUA_SND_DEV_NO_IMMEDIATE_OPEN = 2 + +} pjsua_snd_dev_mode; + + +/** + * This structure specifies the parameters to set the sound device. + * Use pjsua_snd_dev_param_default() to initialize this structure with + * default values. + */ +typedef struct pjsua_snd_dev_param +{ + /* + * Capture dev id. + * + * Default: PJMEDIA_AUD_DEFAULT_CAPTURE_DEV + */ + int capture_dev; + + /* + * Playback dev id. + * + * Default: PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV + */ + int playback_dev; + + /* + * Sound device mode, refer to #pjsua_snd_dev_mode. + * + * Default: 0 + */ + unsigned mode; + +} pjsua_snd_dev_param; + + +/** + * Initialize pjsua_snd_dev_param with default values. + * + * @param prm The parameter. + */ +PJ_DECL(void) pjsua_snd_dev_param_default(pjsua_snd_dev_param *prm); + /** * Get maxinum number of conference ports. @@ -6384,6 +6440,15 @@ PJ_DECL(pj_status_t) pjsua_get_snd_dev(int *capture_dev, PJ_DECL(pj_status_t) pjsua_set_snd_dev(int capture_dev, int playback_dev); +/** + * Select or change sound device according to the specified param. + * + * @param snd_param Sound device param. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjsua_set_snd_dev2(pjsua_snd_dev_param *snd_param); + /** * Set pjsua to use null sound device. The null sound device only provides diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h index dc98cc6f..e1fad139 100644 --- a/pjsip/include/pjsua-lib/pjsua_internal.h +++ b/pjsip/include/pjsua-lib/pjsua_internal.h @@ -478,6 +478,7 @@ struct pjsua_data pjmedia_master_port *null_snd; /**< Master port for null sound. */ pjmedia_port *null_port; /**< Null port. */ pj_bool_t snd_is_on; /**< Media flow is currently active */ + unsigned snd_mode; /**< Sound device mode. */ /* Video device */ pjmedia_vid_dev_index vcap_dev; /**< Capture device ID. */ diff --git a/pjsip/include/pjsua2/media.hpp b/pjsip/include/pjsua2/media.hpp index e642d171..4e42c574 100644 --- a/pjsip/include/pjsua2/media.hpp +++ b/pjsip/include/pjsua2/media.hpp @@ -767,7 +767,9 @@ public: /** * Select or change capture sound device. Application may call this - * function at any time to replace current sound device. + * function at any time to replace current sound device. Calling this + * method will not change the state of the sound device (opened/closed). + * Note that this method will override the mode set by setSndDevMode(). * * @param capture_dev Device ID of the capture device. */ @@ -775,7 +777,9 @@ public: /** * Select or change playback sound device. Application may call this - * function at any time to replace current sound device. + * function at any time to replace current sound device. Calling this + * method will not change the state of the sound device (opened/closed). + * Note that this method will override the mode set by setSndDevMode(). * * @param playback_dev Device ID of the playback device. */ @@ -806,6 +810,15 @@ public: */ MediaPort *setNoDev(); + /** + * Set sound device mode. + * + * @param mode The sound device mode, as bitmask combination + * of #pjsua_snd_dev_mode + * + */ + void setSndDevMode(unsigned mode) const throw(Error); + /** * Change the echo cancellation settings. * diff --git a/pjsip/src/pjsua-lib/pjsua_aud.c b/pjsip/src/pjsua-lib/pjsua_aud.c index 9fc3e533..5ca1b346 100644 --- a/pjsip/src/pjsua-lib/pjsua_aud.c +++ b/pjsip/src/pjsua-lib/pjsua_aud.c @@ -687,6 +687,12 @@ on_return: return status; } +PJ_DEF(void) pjsua_snd_dev_param_default(pjsua_snd_dev_param *prm) +{ + pj_bzero(prm, sizeof(*prm)); + prm->capture_dev = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV; + prm->playback_dev = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV; +} /* * Get maxinum number of conference ports. @@ -1696,6 +1702,7 @@ static pj_status_t open_snd_dev(pjmedia_snd_port_param *param) { pjmedia_port *conf_port; pj_status_t status; + pj_bool_t speaker_only = (pjsua_var.snd_mode & PJSUA_SND_DEV_SPEAKER_ONLY); PJ_ASSERT_RETURN(param, PJ_EINVAL); @@ -1724,15 +1731,29 @@ static pj_status_t open_snd_dev(pjmedia_snd_port_param *param) if (pjsua_var.media_cfg.on_aud_prev_rec_frame) param->on_rec_frame = &on_aud_prev_rec_frame; - PJ_LOG(4,(THIS_FILE, "Opening sound device %s@%d/%d/%dms", + PJ_LOG(4,(THIS_FILE, "Opening sound device (%s) %s@%d/%d/%dms", + speaker_only?"speaker only":"speaker + mic", get_fmt_name(param->base.ext_fmt.id), param->base.clock_rate, param->base.channel_count, param->base.samples_per_frame / param->base.channel_count * 1000 / param->base.clock_rate)); pj_log_push_indent(); - status = pjmedia_snd_port_create2( pjsua_var.snd_pool, - param, &pjsua_var.snd_port); + if (speaker_only) { + status = pjmedia_snd_port_create_player(pjsua_var.snd_pool, + -1, + param->base.clock_rate, + param->base.channel_count, + param->base.samples_per_frame, + param->base.bits_per_sample, + 0, + &pjsua_var.snd_port); + + } else { + status = pjmedia_snd_port_create2(pjsua_var.snd_pool, + param, &pjsua_var.snd_port); + } + if (status != PJ_SUCCESS) goto on_error; @@ -1920,27 +1941,46 @@ static void close_snd_dev(void) } +PJ_DEF(pj_status_t) pjsua_set_snd_dev(int capture_dev, + int playback_dev) +{ + pjsua_snd_dev_param param; + + pjsua_snd_dev_param_default(¶m); + + param.capture_dev = capture_dev; + param.playback_dev = playback_dev; + /* Always open the sound device. */ + param.mode = 0; + + return pjsua_set_snd_dev2(¶m); +} + /* * Select or change sound device. Application may call this function at * any time to replace current sound device. */ -PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev, - int playback_dev) +PJ_DEF(pj_status_t) pjsua_set_snd_dev2(pjsua_snd_dev_param *snd_param) { unsigned alt_cr_cnt = 1; unsigned alt_cr[] = {0, 44100, 48000, 32000, 16000, 8000}; unsigned i; pj_status_t status = -1; + unsigned orig_snd_dev_mode = pjsua_var.snd_mode; + pj_bool_t no_change = (pjsua_var.snd_is_on || (!pjsua_var.snd_is_on && + (snd_param->mode & + PJSUA_SND_DEV_NO_IMMEDIATE_OPEN))); PJ_LOG(4,(THIS_FILE, "Set sound device: capture=%d, playback=%d", - capture_dev, playback_dev)); + snd_param->capture_dev, snd_param->playback_dev)); pj_log_push_indent(); PJSUA_LOCK(); - if (pjsua_var.cap_dev == capture_dev && - pjsua_var.play_dev == playback_dev && - pjsua_var.snd_is_on && !pjsua_var.no_snd) + if (pjsua_var.cap_dev == snd_param->capture_dev && + pjsua_var.play_dev == snd_param->playback_dev && + pjsua_var.snd_mode == snd_param->mode && + !pjsua_var.no_snd && no_change) { PJ_LOG(4, (THIS_FILE, "No changes in capture and playback devices")); PJSUA_UNLOCK(); @@ -1949,13 +1989,28 @@ PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev, } /* Null-sound */ - if (capture_dev==NULL_SND_DEV_ID && playback_dev==NULL_SND_DEV_ID) { + if (snd_param->capture_dev == NULL_SND_DEV_ID && + snd_param->playback_dev == NULL_SND_DEV_ID) + { PJSUA_UNLOCK(); status = pjsua_set_null_snd_dev(); pj_log_pop_indent(); return status; } + pjsua_var.snd_mode = snd_param->mode; + + if (!pjsua_var.no_snd && + (snd_param->mode & PJSUA_SND_DEV_NO_IMMEDIATE_OPEN)) + { + pjsua_var.cap_dev = snd_param->capture_dev; + pjsua_var.play_dev = snd_param->playback_dev; + + PJSUA_UNLOCK(); + pj_log_pop_indent(); + return PJ_SUCCESS; + } + /* Set default clock rate */ alt_cr[0] = pjsua_var.media_cfg.snd_clock_rate; if (alt_cr[0] == 0) @@ -1982,7 +2037,8 @@ PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev, pjsua_var.media_cfg.channel_count / 1000; pjmedia_snd_port_param_default(¶m); param.ec_options = pjsua_var.media_cfg.ec_options; - status = create_aud_param(¶m.base, capture_dev, playback_dev, + status = create_aud_param(¶m.base, snd_param->capture_dev, + snd_param->playback_dev, alt_cr[i], pjsua_var.media_cfg.channel_count, samples_per_frame, 16); if (status != PJ_SUCCESS) @@ -2008,6 +2064,7 @@ PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev, return PJ_SUCCESS; on_error: + pjsua_var.snd_mode = orig_snd_dev_mode; PJSUA_UNLOCK(); pj_log_pop_indent(); return status; diff --git a/pjsip/src/pjsua2/media.cpp b/pjsip/src/pjsua2/media.cpp index 5a4e6ad0..880ade6b 100644 --- a/pjsip/src/pjsua2/media.cpp +++ b/pjsip/src/pjsua2/media.cpp @@ -679,17 +679,29 @@ AudioMedia &AudDevManager::getPlaybackDevMedia() throw(Error) } void AudDevManager::setCaptureDev(int capture_dev) const throw(Error) -{ - int playback_dev = getPlaybackDev(); +{ + pjsua_snd_dev_param param; + pjsua_snd_dev_param_default(¶m); + + param.capture_dev = capture_dev; + param.playback_dev = getPlaybackDev(); - PJSUA2_CHECK_EXPR( pjsua_set_snd_dev(capture_dev, playback_dev) ); + param.mode = PJSUA_SND_DEV_NO_IMMEDIATE_OPEN; + + PJSUA2_CHECK_EXPR( pjsua_set_snd_dev2(¶m) ); } void AudDevManager::setPlaybackDev(int playback_dev) const throw(Error) { - int capture_dev = getCaptureDev(); + pjsua_snd_dev_param param; + pjsua_snd_dev_param_default(¶m); + + param.capture_dev = getCaptureDev(); + param.playback_dev = playback_dev; + + param.mode = PJSUA_SND_DEV_NO_IMMEDIATE_OPEN; - PJSUA2_CHECK_EXPR( pjsua_set_snd_dev(capture_dev, playback_dev) ); + PJSUA2_CHECK_EXPR( pjsua_set_snd_dev2(¶m) ); } const AudioDevInfoVector &AudDevManager::enumDev() throw(Error) @@ -720,6 +732,21 @@ MediaPort *AudDevManager::setNoDev() return (MediaPort*)pjsua_set_no_snd_dev(); } +void AudDevManager::setSndDevMode(unsigned mode) const throw(Error) +{ + int capture_dev = 0, playback_dev = 0; + pjsua_snd_dev_param param; + pj_status_t status = pjsua_get_snd_dev(&capture_dev, &playback_dev); + if (status != PJ_SUCCESS) { + PJSUA2_RAISE_ERROR2(status, "AudDevManager::setSndDevMode()"); + } + pjsua_snd_dev_param_default(¶m); + param.capture_dev = capture_dev; + param.playback_dev = playback_dev; + param.mode = mode; + PJSUA2_CHECK_EXPR( pjsua_set_snd_dev2(¶m) ); +} + void AudDevManager::setEcOptions(unsigned tail_msec, unsigned options) throw(Error) { -- cgit v1.2.3