summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2008-06-13 17:01:46 +0000
committerNanang Izzuddin <nanang@teluu.com>2008-06-13 17:01:46 +0000
commite3399b0820e6010b0a2d423261d54111af63e528 (patch)
tree06cb5c02a9de8441b964f66b8c46da72f936a7b6
parentb7242dd477e952452a5c01b8ab49ae7e41463683 (diff)
Ticket #540: Added pjsua-lib feature auto-close sound device on idle and new pjsua option --snd-auto-close=N
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2018 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip-apps/src/pjsua/pjsua_app.c24
-rw-r--r--pjsip-apps/src/symbian_ua/ua.cpp1
-rw-r--r--pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp1
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h8
-rw-r--r--pjsip/include/pjsua-lib/pjsua_internal.h2
-rw-r--r--pjsip/src/pjsua-lib/pjsua_core.c1
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c102
7 files changed, 118 insertions, 21 deletions
diff --git a/pjsip-apps/src/pjsua/pjsua_app.c b/pjsip-apps/src/pjsua/pjsua_app.c
index d80e16c0..17508bc9 100644
--- a/pjsip-apps/src/pjsua/pjsua_app.c
+++ b/pjsip-apps/src/pjsua/pjsua_app.c
@@ -201,6 +201,9 @@ static void usage(void)
puts (" --playback-dev=id Audio playback device ID (default=-1)");
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 ("");
puts ("Media Transport Options:");
@@ -400,7 +403,7 @@ static pj_status_t parse_args(int argc, char *argv[],
int c;
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,
OPT_100REL, OPT_USE_IMS, OPT_REALM, OPT_USERNAME, OPT_PASSWORD,
@@ -514,6 +517,7 @@ static pj_status_t parse_args(int argc, char *argv[],
{ "playback-lat", 1, 0, OPT_PLAYBACK_LAT},
{ "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}
};
pj_status_t status;
@@ -1108,6 +1112,10 @@ static pj_status_t parse_args(int argc, char *argv[],
cfg->playback_lat = atoi(pj_optarg);
break;
+ case OPT_SND_AUTO_CLOSE:
+ cfg->media_cfg.snd_auto_close_time = atoi(pj_optarg);
+ break;
+
default:
PJ_LOG(1,(THIS_FILE,
"Argument \"%s\" is not valid. Use --help to see help",
@@ -1504,6 +1512,11 @@ static int write_settings(const struct app_config *config,
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);
+ }
/* Sound device latency */
if (config->capture_lat != PJMEDIA_SND_DEFAULT_REC_LATENCY) {
@@ -3786,10 +3799,11 @@ pj_status_t app_init(int argc, char *argv[])
}
#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;
}
diff --git a/pjsip-apps/src/symbian_ua/ua.cpp b/pjsip-apps/src/symbian_ua/ua.cpp
index 34935a18..5396bc72 100644
--- a/pjsip-apps/src/symbian_ua/ua.cpp
+++ b/pjsip-apps/src/symbian_ua/ua.cpp
@@ -334,6 +334,7 @@ static pj_status_t app_startup()
med_cfg.audio_frame_ptime = 40;
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);
if (status != PJ_SUCCESS) {
diff --git a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp
index bd9864b1..7d693b41 100644
--- a/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp
+++ b/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp
@@ -326,6 +326,7 @@ int symbian_ua_init()
med_cfg.audio_frame_ptime = 40;
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;
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index 21d8ffb1..0ee97f9c 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -3908,6 +3908,14 @@ struct pjsua_media_config
* Specify the credential to authenticate with the TURN server.
*/
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;
};
diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h
index dfb9f84a..766d8782 100644
--- a/pjsip/include/pjsua-lib/pjsua_internal.h
+++ b/pjsip/include/pjsua-lib/pjsua_internal.h
@@ -236,7 +236,9 @@ struct pjsua_data
int cap_dev; /**< Capture device ID. */
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. */
diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c
index a50ff433..a59e9346 100644
--- a/pjsip/src/pjsua-lib/pjsua_core.c
+++ b/pjsip/src/pjsua-lib/pjsua_core.c
@@ -171,6 +171,7 @@ PJ_DEF(void) pjsua_media_config_default(pjsua_media_config *cfg)
cfg->ilbc_mode = PJSUA_DEFAULT_ILBC_MODE;
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;
}
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index d8c2cd9c..0f923452 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -22,7 +22,9 @@
#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
# define PJSUA_REQUIRE_CONSECUTIVE_RTCP_PORT 0
@@ -423,6 +425,20 @@ on_error:
return status;
}
+/* 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();
+}
+
/*
* Start pjsua media subsystem.
@@ -444,16 +460,8 @@ pj_status_t pjsua_media_subsys_start(void)
return status;
}
- /* 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;
}
@@ -1327,6 +1335,25 @@ PJ_DEF(pj_status_t) pjsua_conf_remove_port(pjsua_conf_port_id id)
PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source,
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);
}
@@ -1337,7 +1364,31 @@ PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source,
PJ_DEF(pj_status_t) pjsua_conf_disconnect( pjsua_conf_port_id source,
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;
}
@@ -1843,6 +1894,10 @@ static void close_snd_dev(void)
pjmedia_master_port_destroy(pjsua_var.null_snd, PJ_FALSE);
pjsua_var.null_snd = NULL;
}
+
+ if (pjsua_var.snd_pool)
+ pj_pool_release(pjsua_var.snd_pool);
+ pjsua_var.snd_pool = NULL;
}
/*
@@ -1863,9 +1918,17 @@ PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev,
pj_str_t tmp;
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 */
clock_rates[0] = pjsua_var.media_cfg.snd_clock_rate;
@@ -1887,7 +1950,7 @@ PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev,
/* 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],
pjsua_var.media_cfg.channel_count,
@@ -1914,7 +1977,7 @@ PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev,
resample_opt |= PJMEDIA_RESAMPLE_USE_LINEAR;
}
- status = pjmedia_resample_port_create(pjsua_var.pool,
+ status = pjmedia_resample_port_create(pjsua_var.snd_pool,
conf_port,
selected_clock_rate,
resample_opt,
@@ -1948,7 +2011,7 @@ PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev,
}
/* 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);
@@ -2019,6 +2082,10 @@ PJ_DEF(pj_status_t) pjsua_set_null_snd_dev(void)
/* Close existing sound device */
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.."));
/* Get the port0 of the conference bridge. */
@@ -2028,7 +2095,7 @@ PJ_DEF(pj_status_t) pjsua_set_null_snd_dev(void)
/* Create master port, connecting port0 of the conference bridge to
* 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) {
pjsua_perror(THIS_FILE, "Unable to create null sound device",
@@ -2040,6 +2107,9 @@ PJ_DEF(pj_status_t) pjsua_set_null_snd_dev(void)
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;
}