Index: /pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- /pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 631)
+++ /pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 632)
@@ -22,4 +22,5 @@
 #define THIS_FILE	"pjsua.c"
 
+//#define STEREO_DEMO
 
 
@@ -55,4 +56,9 @@
     unsigned		    auto_answer;
     unsigned		    duration;
+
+#ifdef STEREO_DEMO
+    pjmedia_snd_port	   *snd;
+#endif
+
 } app_config;
 
@@ -61,4 +67,6 @@
 static pjsua_call_id	current_call;
 static pj_str_t		uri_arg;
+
+static void stereo_demo();
 
 /*****************************************************************************
@@ -2200,4 +2208,8 @@
 	return status;
 
+#ifdef STEREO_DEMO
+    stereo_demo();
+#endif
+
     /* Optionally registers WAV file */
     if (app_config.wav_file.slen) {
@@ -2273,4 +2285,5 @@
 
     /* Use null sound device? */
+#ifndef STEREO_DEMO
     if (app_config.null_audio) {
 	status = pjsua_set_null_snd_dev();
@@ -2278,4 +2291,5 @@
 	    return status;
     }
+#endif
 
     return PJ_SUCCESS;
@@ -2305,4 +2319,11 @@
 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);
@@ -2312,2 +2333,63 @@
     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
+
Index: /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 631)
+++ /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 632)
@@ -2248,4 +2248,34 @@
 
 /**
+ * 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
@@ -2425,4 +2455,15 @@
 
 
+/**
+ * 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.
Index: /pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 631)
+++ /pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 632)
@@ -205,4 +205,5 @@
     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.	*/
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 631)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 632)
@@ -340,5 +340,7 @@
 
     /* 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) {
@@ -572,4 +574,33 @@
 
 /*
+ * 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. 
  */
@@ -963,4 +994,19 @@
 
 
+
+/*
+ * 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.
