Index: pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 2017)
+++ pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 2018)
@@ -202,4 +202,7 @@
     puts  ("  --capture-lat=N     Audio capture latency, in ms (default=10)");
     puts  ("  --playback-lat=N    Audio playback latency, in ms (default=100)");
+    puts  ("  --snd-auto-close=N  Auto close audio device when it is idle for N seconds.");
+    puts  ("                      Specify N=-1 (default) to disable this feature.");
+    puts  ("                      Specify N=0 for instant close when unused.");
 
     puts  ("");
@@ -401,5 +404,5 @@
     int option_index;
     enum { OPT_CONFIG_FILE=127, OPT_LOG_FILE, OPT_LOG_LEVEL, OPT_APP_LOG_LEVEL, 
-	   OPT_HELP, OPT_VERSION, OPT_NULL_AUDIO, 
+	   OPT_HELP, OPT_VERSION, OPT_NULL_AUDIO, OPT_SND_AUTO_CLOSE,
 	   OPT_LOCAL_PORT, OPT_IP_ADDR, OPT_PROXY, OPT_OUTBOUND_PROXY, 
 	   OPT_REGISTRAR, OPT_REG_TIMEOUT, OPT_PUBLISH, OPT_ID, OPT_CONTACT,
@@ -515,4 +518,5 @@
 	{ "stdout-refresh", 1, 0, OPT_STDOUT_REFRESH},
 	{ "stdout-refresh-text", 1, 0, OPT_STDOUT_REFRESH_TEXT},
+	{ "snd-auto-close", 1, 0, OPT_SND_AUTO_CLOSE},
 	{ NULL, 0, 0, 0}
     };
@@ -1107,4 +1111,8 @@
 	case OPT_PLAYBACK_LAT:
 	    cfg->playback_lat = atoi(pj_optarg);
+	    break;
+
+	case OPT_SND_AUTO_CLOSE:
+	    cfg->media_cfg.snd_auto_close_time = atoi(pj_optarg);
 	    break;
 
@@ -1503,4 +1511,9 @@
     if (config->playback_dev != PJSUA_INVALID_ID) {
 	pj_ansi_sprintf(line, "--playback-dev %d\n", config->playback_dev);
+	pj_strcat2(&cfg, line);
+    }
+    if (config->media_cfg.snd_auto_close_time != -1) {
+	pj_ansi_sprintf(line, "--snd-auto-close %d\n", 
+			config->media_cfg.snd_auto_close_time);
 	pj_strcat2(&cfg, line);
     }
@@ -3787,8 +3800,9 @@
 #endif
 
-    if (app_config.capture_dev != PJSUA_INVALID_ID
-        || app_config.playback_dev != PJSUA_INVALID_ID) {
-	status
-	  = pjsua_set_snd_dev(app_config.capture_dev, app_config.playback_dev);
+    if (app_config.capture_dev  != PJSUA_INVALID_ID ||
+        app_config.playback_dev != PJSUA_INVALID_ID) 
+    {
+	status = pjsua_set_snd_dev(app_config.capture_dev, 
+				   app_config.playback_dev);
 	if (status != PJ_SUCCESS)
 	    goto on_error;
Index: pjproject/trunk/pjsip-apps/src/symbian_ua/ua.cpp
===================================================================
--- pjproject/trunk/pjsip-apps/src/symbian_ua/ua.cpp	(revision 2017)
+++ pjproject/trunk/pjsip-apps/src/symbian_ua/ua.cpp	(revision 2018)
@@ -335,4 +335,5 @@
     med_cfg.ec_tail_len = 0;
     med_cfg.enable_ice = USE_ICE;
+    med_cfg.snd_auto_close_time = 5; // wait for 5 seconds idle before sound dev get auto-closed
     
     status = pjsua_init(&cfg, &log_cfg, &med_cfg);
Index: pjproject/trunk/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp
===================================================================
--- pjproject/trunk/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp	(revision 2017)
+++ pjproject/trunk/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp	(revision 2018)
@@ -327,4 +327,5 @@
     med_cfg.ec_tail_len = 0;
     med_cfg.enable_ice = USE_ICE;
+    med_cfg.snd_auto_close_time = 5; // wait for 5 seconds idle before sound dev get auto-closed
 
     pjsua_logging_config log_cfg;
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 2017)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 2018)
@@ -3909,4 +3909,12 @@
      */
     pj_stun_auth_cred	turn_auth_cred;
+
+    /**
+     * Specify idle time of sound device before it is automatically closed,
+     * in seconds.
+     *
+     * Default : -1 (Disable the auto-close feature of sound device)
+     */
+    int			snd_auto_close_time;
 };
 
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 2017)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 2018)
@@ -237,5 +237,7 @@
     int			 play_dev;  /**< Playback device ID.		*/
     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.			*/
+    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.			*/
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 2017)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 2018)
@@ -172,4 +172,5 @@
     cfg->ec_tail_len = PJSUA_DEFAULT_EC_TAIL_LEN;
     cfg->jb_init = cfg->jb_min_pre = cfg->jb_max_pre = cfg->jb_max = -1;
+    cfg->snd_auto_close_time = -1;
 
     cfg->turn_conn_type = PJ_TURN_TP_UDP;
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 2017)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 2018)
@@ -23,5 +23,7 @@
 #define THIS_FILE		"pjsua_media.c"
 
-#define DEFAULT_RTP_PORT			4000
+#define DEFAULT_RTP_PORT	4000
+
+#define NULL_SND_DEV_ID		-99
 
 #ifndef PJSUA_REQUIRE_CONSECUTIVE_RTCP_PORT
@@ -424,4 +426,18 @@
 }
 
+/* Timer callback to close sound device */
+static void close_snd_timer_cb( pj_timer_heap_t *th,
+				pj_timer_entry *entry)
+{
+    PJ_UNUSED_ARG(th);
+
+    PJ_LOG(4,(THIS_FILE,"Closing sound device after idle for %d seconds", 
+	      pjsua_var.media_cfg.snd_auto_close_time));
+
+    entry->id = PJ_FALSE;
+
+    close_snd_dev();
+}
+
 
 /*
@@ -445,14 +461,6 @@
     }
 
-    /* Create sound port if none is created yet */
-    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) {
-	    pjsua_perror(THIS_FILE, "Error opening sound device", status);
-	    return status;
-	}
-    }
+    pj_timer_entry_init(&pjsua_var.snd_idle_timer, PJ_FALSE, NULL, 
+			&close_snd_timer_cb);
 
     return PJ_SUCCESS;
@@ -1328,4 +1336,23 @@
 					pjsua_conf_port_id sink)
 {
+    /* If sound device idle timer is active, cancel it first. */
+    if (pjsua_var.snd_idle_timer.id) {
+	pjsip_endpt_cancel_timer(pjsua_var.endpt, &pjsua_var.snd_idle_timer);
+	pjsua_var.snd_idle_timer.id = PJ_FALSE;
+    }
+
+    /* Create sound port if none is instantiated */
+    if (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL && 
+	!pjsua_var.no_snd) 
+    {
+	pj_status_t status;
+
+	status = pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev);
+	if (status != PJ_SUCCESS) {
+	    pjsua_perror(THIS_FILE, "Error opening sound device", status);
+	    return status;
+	}
+    }
+
     return pjmedia_conf_connect_port(pjsua_var.mconf, source, sink, 0);
 }
@@ -1338,5 +1365,29 @@
 					   pjsua_conf_port_id sink)
 {
-    return pjmedia_conf_disconnect_port(pjsua_var.mconf, source, sink);
+    pj_status_t status;
+
+    status = pjmedia_conf_disconnect_port(pjsua_var.mconf, source, sink);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    /* If no port is connected, sound device must be idle. Activate sound 
+     * device auto-close timer.
+     */
+    if ((pjsua_var.snd_port!=NULL || pjsua_var.null_snd!=NULL) && 
+	pjsua_var.snd_idle_timer.id==PJ_FALSE &&
+	pjmedia_conf_get_connect_count(pjsua_var.mconf) == 0 &&
+	pjsua_var.media_cfg.snd_auto_close_time >= 0)
+    {
+	pj_time_val delay;
+
+	delay.msec = 0;
+	delay.sec = pjsua_var.media_cfg.snd_auto_close_time;
+
+	pjsua_var.snd_idle_timer.id = PJ_TRUE;
+	pjsip_endpt_schedule_timer(pjsua_var.endpt, &pjsua_var.snd_idle_timer, 
+				   &delay);
+    }
+
+    return status;
 }
 
@@ -1844,4 +1895,8 @@
 	pjsua_var.null_snd = NULL;
     }
+
+    if (pjsua_var.snd_pool) 
+	pj_pool_release(pjsua_var.snd_pool);
+    pjsua_var.snd_pool = NULL;
 }
 
@@ -1864,7 +1919,15 @@
     pj_status_t status = -1;
 
+    /* Check if NULL sound device is used */
+    if (NULL_SND_DEV_ID == capture_dev || NULL_SND_DEV_ID == playback_dev) {
+	return pjsua_set_null_snd_dev();
+    }
+
     /* Close existing sound port */
     close_snd_dev();
 
+    /* Create memory pool for sound device. */
+    pjsua_var.snd_pool = pjsua_pool_create("pjsua_snd", 4000, 4000);
+    PJ_ASSERT_RETURN(pjsua_var.snd_pool, PJ_ENOMEM);
 
     /* Set default clock rate */
@@ -1888,5 +1951,5 @@
 	/* Create the sound device. Sound port will start immediately. */
 	fps = 1000 / pjsua_var.media_cfg.audio_frame_ptime;
-	status = pjmedia_snd_port_create(pjsua_var.pool, capture_dev,
+	status = pjmedia_snd_port_create(pjsua_var.snd_pool, capture_dev,
 					 playback_dev, 
 					 clock_rates[i], 
@@ -1915,5 +1978,5 @@
 		}
 		
-		status = pjmedia_resample_port_create(pjsua_var.pool, 
+		status = pjmedia_resample_port_create(pjsua_var.snd_pool, 
 						      conf_port,
 						      selected_clock_rate,
@@ -1949,5 +2012,5 @@
 
     /* Set AEC */
-    pjmedia_snd_port_set_ec( pjsua_var.snd_port, pjsua_var.pool, 
+    pjmedia_snd_port_set_ec( pjsua_var.snd_port, pjsua_var.snd_pool, 
 			     pjsua_var.media_cfg.ec_tail_len, 
 			     pjsua_var.media_cfg.ec_options);
@@ -2020,4 +2083,8 @@
     close_snd_dev();
 
+    /* Create memory pool for sound device. */
+    pjsua_var.snd_pool = pjsua_pool_create("pjsua_snd", 4000, 4000);
+    PJ_ASSERT_RETURN(pjsua_var.snd_pool, PJ_ENOMEM);
+
     PJ_LOG(4,(THIS_FILE, "Opening null sound device.."));
 
@@ -2029,5 +2096,5 @@
      * a null port.
      */
-    status = pjmedia_master_port_create(pjsua_var.pool, pjsua_var.null_port,
+    status = pjmedia_master_port_create(pjsua_var.snd_pool, pjsua_var.null_port,
 					conf_port, 0, &pjsua_var.null_snd);
     if (status != PJ_SUCCESS) {
@@ -2040,4 +2107,7 @@
     status = pjmedia_master_port_start(pjsua_var.null_snd);
     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+    pjsua_var.cap_dev = NULL_SND_DEV_ID;
+    pjsua_var.play_dev = NULL_SND_DEV_ID;
 
     return PJ_SUCCESS;
