summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pjsip-apps/src/pjsua/pjsua_app.c82
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h41
-rw-r--r--pjsip/include/pjsua-lib/pjsua_internal.h1
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c48
4 files changed, 171 insertions, 1 deletions
diff --git a/pjsip-apps/src/pjsua/pjsua_app.c b/pjsip-apps/src/pjsua/pjsua_app.c
index e48d2cb4..d8d30dc7 100644
--- a/pjsip-apps/src/pjsua/pjsua_app.c
+++ b/pjsip-apps/src/pjsua/pjsua_app.c
@@ -21,6 +21,7 @@
#define THIS_FILE "pjsua.c"
+//#define STEREO_DEMO
/* Pjsua application data */
@@ -54,6 +55,11 @@ static struct app_config
unsigned ptime;
unsigned auto_answer;
unsigned duration;
+
+#ifdef STEREO_DEMO
+ pjmedia_snd_port *snd;
+#endif
+
} app_config;
@@ -61,6 +67,8 @@ static pjsua_acc_id current_acc;
static pjsua_call_id current_call;
static pj_str_t uri_arg;
+static void stereo_demo();
+
/*****************************************************************************
* Configuration manipulation
*/
@@ -2199,6 +2207,10 @@ pj_status_t app_init(int argc, char *argv[])
if (status != PJ_SUCCESS)
return status;
+#ifdef STEREO_DEMO
+ stereo_demo();
+#endif
+
/* Optionally registers WAV file */
if (app_config.wav_file.slen) {
status = pjsua_player_create(&app_config.wav_file, 0,
@@ -2272,11 +2284,13 @@ pj_status_t app_init(int argc, char *argv[])
goto on_error;
/* Use null sound device? */
+#ifndef STEREO_DEMO
if (app_config.null_audio) {
status = pjsua_set_null_snd_dev();
if (status != PJ_SUCCESS)
return status;
}
+#endif
return PJ_SUCCESS;
@@ -2304,6 +2318,13 @@ pj_status_t app_main(void)
pj_status_t app_destroy(void)
{
+#ifdef STEREO_DEMO
+ if (app_config.snd) {
+ pjmedia_snd_port_destroy(app_config.snd);
+ app_config.snd = NULL;
+ }
+#endif
+
if (app_config.pool) {
pj_pool_release(app_config.pool);
app_config.pool = NULL;
@@ -2311,3 +2332,64 @@ pj_status_t app_destroy(void)
return pjsua_destroy();
}
+
+
+#ifdef STEREO_DEMO
+static void stereo_demo()
+{
+ pjmedia_port *conf, *splitter, *ch1;
+ unsigned clock;
+ pj_status_t status;
+
+ /* Disable existing sound device */
+ conf = pjsua_set_no_snd_dev();
+
+ clock = app_config.media_cfg.clock_rate;
+
+ /* Create stereo-mono splitter/combiner */
+ status = pjmedia_splitcomb_create(app_config.pool,
+ clock /* clock rate */,
+ 2 /* stereo */,
+ clock*2*10/1000/* 10ms samples * 2ch */,
+ 16 /* bits */,
+ 0 /* options */,
+ &splitter);
+ pj_assert(status == PJ_SUCCESS);
+
+ /* Connect channel0 (left channel?) to conference port slot0 */
+ status = pjmedia_splitcomb_set_channel(splitter, 0 /* ch0 */,
+ 0 /*options*/,
+ conf);
+ pj_assert(status == PJ_SUCCESS);
+
+ /* Create reverse channel for channel1 (right channel?)... */
+ status = pjmedia_splitcomb_create_rev_channel(app_config.pool,
+ splitter,
+ 1 /* ch1 */,
+ 0 /* options */,
+ &ch1);
+ pj_assert(status == PJ_SUCCESS);
+
+ /* .. and register it to conference bridge (it would be slot1
+ * if there's no other devices connected to the bridge)
+ */
+ status = pjsua_conf_add_port(app_config.pool, ch1, NULL);
+ pj_assert(status == PJ_SUCCESS);
+
+ /* Create sound device */
+ status = pjmedia_snd_port_create(app_config.pool, -1, -1,
+ clock /* clock rate */,
+ 2 /* stereo */,
+ clock*2*10/1000 /* 10 ms samples * 2ch */,
+ 16 /* bits */,
+ 0, &app_config.snd);
+ pj_assert(status == PJ_SUCCESS);
+
+
+ /* Connect the splitter to the sound device */
+ status = pjmedia_snd_port_connect(app_config.snd, splitter);
+ pj_assert(status == PJ_SUCCESS);
+
+}
+#endif
+
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index 07287a0a..6958bc4f 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -2247,6 +2247,36 @@ PJ_DECL(pj_status_t) pjsua_conf_get_port_info( pjsua_conf_port_id id,
/**
+ * Add arbitrary media port to PJSUA's conference bridge. Application
+ * can use this function to add the media port that it creates. For
+ * media ports that are created by PJSUA-LIB (such as calls, file player,
+ * or file recorder), PJSUA-LIB will automatically add the port to
+ * the bridge.
+ *
+ * @param pool Pool to use.
+ * @param port Media port to be added to the bridge.
+ * @param p_id Optional pointer to receive the conference
+ * slot id.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_conf_add_port(pj_pool_t *pool,
+ pjmedia_port *port,
+ pjsua_conf_port_id *p_id);
+
+
+/**
+ * Remove arbitrary slot from the conference bridge. Application should only
+ * call this function if it registered the port manually.
+ *
+ * @param id The slot id of the port to be removed.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_conf_remove_port(pjsua_conf_port_id id);
+
+
+/**
* Establish unidirectional media flow from souce to sink. One source
* may transmit to multiple destinations/sink. And if multiple
* sources are transmitting to the same sink, the media will be mixed
@@ -2424,6 +2454,17 @@ PJ_DECL(pj_status_t) pjsua_set_snd_dev(int capture_dev,
PJ_DECL(pj_status_t) pjsua_set_null_snd_dev(void);
+/**
+ * Disconnect the main conference bridge from any sound devices, and let
+ * application connect the bridge to it's own sound device/master port.
+ *
+ * @return The port interface of the conference bridge,
+ * so that application can connect this to it's own
+ * sound device or master port.
+ */
+PJ_DECL(pjmedia_port*) pjsua_set_no_snd_dev(void);
+
+
/*****************************************************************************
* Codecs.
*/
diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h
index fe57b451..c862219f 100644
--- a/pjsip/include/pjsua-lib/pjsua_internal.h
+++ b/pjsip/include/pjsua-lib/pjsua_internal.h
@@ -204,6 +204,7 @@ struct pjsua_data
pjmedia_conf *mconf; /**< Conference bridge. */
int cap_dev; /**< Capture device ID. */
int play_dev; /**< Playback device ID. */
+ pj_bool_t no_snd; /**< No sound (app will manage it) */
pjmedia_snd_port *snd_port; /**< Sound port. */
pjmedia_master_port *null_snd; /**< Master port for null sound. */
pjmedia_port *null_port; /**< Null port. */
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index a25c6745..c8c20490 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -339,7 +339,9 @@ pj_status_t pjsua_media_subsys_start(void)
}
/* Create sound port if none is created yet */
- if (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL) {
+ if (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL &&
+ !pjsua_var.no_snd)
+ {
status = pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev);
if (status != PJ_SUCCESS) {
/* Error opening sound device, use null device */
@@ -571,6 +573,35 @@ PJ_DEF(pj_status_t) pjsua_conf_get_port_info( pjsua_conf_port_id id,
/*
+ * Add arbitrary media port to PJSUA's conference bridge.
+ */
+PJ_DEF(pj_status_t) pjsua_conf_add_port( pj_pool_t *pool,
+ pjmedia_port *port,
+ pjsua_conf_port_id *p_id)
+{
+ pj_status_t status;
+
+ status = pjmedia_conf_add_port(pjsua_var.mconf, pool,
+ port, NULL, (unsigned*)p_id);
+ if (status != PJ_SUCCESS) {
+ if (p_id)
+ *p_id = PJSUA_INVALID_ID;
+ }
+
+ return status;
+}
+
+
+/*
+ * Remove arbitrary slot from the conference bridge.
+ */
+PJ_DEF(pj_status_t) pjsua_conf_remove_port(pjsua_conf_port_id id)
+{
+ return pjmedia_conf_remove_port(pjsua_var.mconf, (unsigned)id);
+}
+
+
+/*
* Establish unidirectional media flow from souce to sink.
*/
PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source,
@@ -962,6 +993,21 @@ PJ_DEF(pj_status_t) pjsua_set_null_snd_dev(void)
}
+
+/*
+ * Use no device!
+ */
+PJ_DEF(pjmedia_port*) pjsua_set_no_snd_dev(void)
+{
+ /* Close existing sound device */
+ close_snd_dev();
+
+ pjsua_var.no_snd = PJ_TRUE;
+ return pjmedia_conf_get_master_port(pjsua_var.mconf);
+}
+
+
+
/*****************************************************************************
* Codecs.
*/