aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES6
-rw-r--r--apps/app_meetme.c188
-rw-r--r--doc/tex/channelvariables.tex15
3 files changed, 195 insertions, 14 deletions
diff --git a/CHANGES b/CHANGES
index 0dc364822..98770b31f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -185,6 +185,10 @@ MeetMe Changes
the schedule start time, or to allow the caller to join the conference early.
Also included is optional support for limiting the number of callers per
RealTime conference.
+ * Added the S() and L() options to the MeetMe application. These are pretty
+ much identical to the S() and L() options to Dial(). They let you set
+ timeouts for the conference, as well as have warning sounds played to
+ let the caller know how much time is left, and when it is running out.
Music On Hold Changes
---------------------
@@ -307,4 +311,4 @@ Miscellaneous
configs/extensions.lua.sample for examples of how to do this.
* Added a new channel driver, chan_unistim. See doc/unistim.txt and
configs/unistim.conf.sample for details. This new channel driver allows
- you to use Nortel i2002, i2004, and i2050 phones with Asterisk.
+ you to use Nortel i2002, i2004, and i2050 phones with Asterisk.
diff --git a/apps/app_meetme.c b/apps/app_meetme.c
index 472a33263..cd8b377f5 100644
--- a/apps/app_meetme.c
+++ b/apps/app_meetme.c
@@ -163,13 +163,17 @@ enum {
CONFFLAG_SLA_STATION = (1 << 26),
CONFFLAG_SLA_TRUNK = (1 << 27),
/*! If set, the user should continue in the dialplan if kicked out */
- CONFFLAG_KICK_CONTINUE = (1 << 28)
+ CONFFLAG_KICK_CONTINUE = (1 << 28),
+ CONFFLAG_DURATION_STOP = (1 << 29),
+ CONFFLAG_DURATION_LIMIT = (1 << 30),
};
enum {
OPT_ARG_WAITMARKED = 0,
OPT_ARG_EXITKEYS = 1,
- OPT_ARG_ARRAY_SIZE = 2,
+ OPT_ARG_DURATION_STOP = 2,
+ OPT_ARG_DURATION_LIMIT = 3,
+ OPT_ARG_ARRAY_SIZE = 4,
};
AST_APP_OPTIONS(meetme_opts, BEGIN_OPTIONS
@@ -199,6 +203,8 @@ AST_APP_OPTIONS(meetme_opts, BEGIN_OPTIONS
AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT ),
AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT ),
AST_APP_OPTION('1', CONFFLAG_NOONLYPERSON ),
+ AST_APP_OPTION_ARG('S', CONFFLAG_DURATION_STOP, OPT_ARG_DURATION_STOP),
+ AST_APP_OPTION_ARG('L', CONFFLAG_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
END_OPTIONS );
static const char *app = "MeetMe";
@@ -273,7 +279,15 @@ static const char *descrip =
" 'X' -- allow user to exit the conference by entering a valid single\n"
" digit extension ${MEETME_EXIT_CONTEXT} or the current context\n"
" if that variable is not defined.\n"
-" '1' -- do not play message when first person enters\n";
+" '1' -- do not play message when first person enters\n"
+" 'S(x)' -- Kick the user 'x' seconds *after* he entered into the conference.\n"
+" 'L(x[:y][:z])' - Limit the conference to 'x' ms. Play a warning when 'y' ms are\n"
+" left. Repeat the warning every 'z' ms. The following special\n"
+" variables can be used with this option:\n"
+" * CONF_LIMIT_TIMEOUT_FILE File to play when time is up.\n"
+" * CONF_LIMIT_WARNING_FILE File to play as warning if 'y' is defined.\n"
+" The default is to say the time remaining.\n"
+"";
static const char *descrip2 =
" MeetMeCount(confno[,var]): Plays back the number of users in the specified\n"
@@ -394,6 +408,13 @@ struct ast_conf_user {
char usrvalue[50]; /*!< Custom User Value */
char namerecloc[PATH_MAX]; /*!< Name Recorded file Location */
time_t jointime; /*!< Time the user joined the conference */
+ time_t kicktime; /*!< Time the user will be kicked from the conference */
+ struct timeval start_time; /*!< Time the user entered into the conference */
+ long timelimit; /*!< Time limit for the user to be in the conference L(x:y:z) */
+ long play_warning; /*!< Play a warning when 'y' ms are left */
+ long warning_freq; /*!< Repeat the warning every 'z' ms */
+ const char *warning_sound; /*!< File to play as warning if 'y' is defined */
+ const char *end_sound; /*!< File to play when time is up. */
struct volume talk;
struct volume listen;
AST_LIST_ENTRY(ast_conf_user) list;
@@ -1471,7 +1492,18 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
char *buf = __buf + AST_FRIENDLY_OFFSET;
char *exitkeys = NULL;
-
+ time_t myt;
+ unsigned int calldurationlimit = 0;
+ long timelimit = 0;
+ long play_warning = 0;
+ long warning_freq = 0;
+ const char *warning_sound = NULL;
+ const char *end_sound = NULL;
+ char *parse;
+ long time_left_ms = 0;
+ struct timeval nexteventts = { 0, };
+ int to;
+
if (!(user = ast_calloc(1, sizeof(*user))))
return ret;
@@ -1482,7 +1514,64 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
(opt_waitmarked_timeout > 0)) {
timeout = time(NULL) + opt_waitmarked_timeout;
}
-
+
+ if ((confflags & CONFFLAG_DURATION_STOP) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_STOP])) {
+ calldurationlimit = atoi(optargs[OPT_ARG_DURATION_STOP]);
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n",calldurationlimit);
+ }
+
+ if ((confflags & CONFFLAG_DURATION_LIMIT) && !ast_strlen_zero(optargs[OPT_ARG_DURATION_LIMIT])) {
+ char *limit_str, *warning_str, *warnfreq_str;
+ const char *var;
+
+ parse = optargs[OPT_ARG_DURATION_LIMIT];
+ limit_str = strsep(&parse, ":");
+ warning_str = strsep(&parse, ":");
+ warnfreq_str = parse;
+
+ timelimit = atol(limit_str);
+ if (warning_str)
+ play_warning = atol(warning_str);
+ if (warnfreq_str)
+ warning_freq = atol(warnfreq_str);
+
+ if (!timelimit) {
+ timelimit = play_warning = warning_freq = 0;
+ warning_sound = NULL;
+ } else if (play_warning > timelimit) {
+ if (!warning_freq) {
+ play_warning = 0;
+ } else {
+ while (play_warning > timelimit)
+ play_warning -= warning_freq;
+ if (play_warning < 1)
+ play_warning = warning_freq = 0;
+ }
+ }
+
+ var = pbx_builtin_getvar_helper(chan,"CONF_LIMIT_WARNING_FILE");
+ warning_sound = var ? var : "timeleft";
+
+ var = pbx_builtin_getvar_helper(chan,"CONF_LIMIT_TIMEOUT_FILE");
+ end_sound = var ? var : NULL;
+
+ /* undo effect of S(x) in case they are both used */
+ calldurationlimit = 0;
+ /* more efficient do it like S(x) does since no advanced opts */
+ if (!play_warning && !end_sound && timelimit) {
+ calldurationlimit = timelimit / 1000;
+ timelimit = play_warning = warning_freq = 0;
+ } else {
+ ast_debug(2, "Limit Data for this call:\n");
+ ast_debug(2, "- timelimit = %ld\n", timelimit);
+ ast_debug(2, "- play_warning = %ld\n", play_warning);
+ ast_debug(2, "- warning_freq = %ld\n", warning_freq);
+ ast_debug(2, "- warning_sound = %s\n", warning_sound ? warning_sound : "UNDEF");
+ ast_debug(2, "- end_sound = %s\n", end_sound ? end_sound : "UNDEF");
+ }
+ }
+
/* Get exit keys */
if ((confflags & CONFFLAG_KEYEXIT)) {
if (!ast_strlen_zero(optargs[OPT_ARG_EXITKEYS]))
@@ -1526,6 +1615,26 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
ast_mutex_unlock(&conf->recordthreadlock);
time(&user->jointime);
+
+ user->timelimit = timelimit;
+ user->play_warning = play_warning;
+ user->warning_freq = warning_freq;
+ user->warning_sound = warning_sound;
+ user->end_sound = end_sound;
+
+ if (calldurationlimit > 0) {
+ time(&user->kicktime);
+ user->kicktime = user->kicktime + calldurationlimit;
+ }
+
+ if (ast_tvzero(user->start_time))
+ user->start_time = ast_tvnow();
+ time_left_ms = user->timelimit;
+
+ if (user->timelimit) {
+ nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000));
+ nexteventts = ast_tvsub(nexteventts, ast_samp2tv(user->play_warning, 1000));
+ }
if (conf->locked && (!(confflags & CONFFLAG_ADMIN))) {
/* Sorry, but this conference is locked! */
@@ -1810,6 +1919,9 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
for (;;) {
int menu_was_active = 0;
+ outfd = -1;
+ ms = -1;
+
if (rt_schedule) {
char currenttime[32];
struct ast_tm tm;
@@ -1846,8 +1958,70 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
}
}
- outfd = -1;
- ms = -1;
+ time(&myt); /* get current time */
+ if (user->kicktime && (user->kicktime < myt))
+ break;
+
+ to = -1;
+ if (user->timelimit) {
+ struct timeval now;
+ int minutes = 0, seconds = 0, remain = 0;
+
+ now = ast_tvnow();
+ to = ast_tvdiff_ms(nexteventts, now);
+ if (to < 0)
+ to = 0;
+ time_left_ms = user->timelimit - ast_tvdiff_ms(now, user->start_time);
+ if (time_left_ms < to)
+ to = time_left_ms;
+
+ if (time_left_ms <= 0) {
+ if (user->end_sound){
+ res = ast_streamfile(chan, user->end_sound, chan->language);
+ res = ast_waitstream(chan, "");
+ }
+ break;
+ }
+
+ if (!to) {
+ if (time_left_ms >= 5000) {
+
+ remain = (time_left_ms + 500) / 1000;
+ if (remain / 60 >= 1) {
+ minutes = remain / 60;
+ seconds = remain % 60;
+ } else {
+ seconds = remain;
+ }
+
+ /* force the time left to round up if appropriate */
+ if (user->warning_sound && user->play_warning){
+ if (!strcmp(user->warning_sound,"timeleft")) {
+
+ res = ast_streamfile(chan, "vm-youhave", chan->language);
+ res = ast_waitstream(chan, "");
+ if (minutes) {
+ res = ast_say_number(chan, minutes, AST_DIGIT_ANY, chan->language, (char *) NULL);
+ res = ast_streamfile(chan, "queue-minutes", chan->language);
+ res = ast_waitstream(chan, "");
+ }
+ if (seconds) {
+ res = ast_say_number(chan, seconds, AST_DIGIT_ANY, chan->language, (char *) NULL);
+ res = ast_streamfile(chan, "queue-seconds", chan->language);
+ res = ast_waitstream(chan, "");
+ }
+ } else {
+ res = ast_streamfile(chan, user->warning_sound, chan->language);
+ res = ast_waitstream(chan, "");
+ }
+ }
+ }
+ if (user->warning_freq)
+ nexteventts = ast_tvadd(nexteventts, ast_samp2tv(user->warning_freq, 1000));
+ else
+ nexteventts = ast_tvadd(user->start_time, ast_samp2tv(user->timelimit, 1000));
+ }
+ }
if (timeout && time(NULL) >= timeout)
break;
diff --git a/doc/tex/channelvariables.tex b/doc/tex/channelvariables.tex
index 4aa78f176..1d2bc8213 100644
--- a/doc/tex/channelvariables.tex
+++ b/doc/tex/channelvariables.tex
@@ -840,12 +840,15 @@ ${VPB_GETDTMF} chan_vpb
\subsection{The MeetMe Conference Bridge}
\begin{verbatim}
-${MEETME_RECORDINGFILE} Name of file for recording a conference with
- the "r" option
-${MEETME_RECORDINGFORMAT} Format of file to be recorded
-${MEETME_EXIT_CONTEXT} Context for exit out of meetme meeting
-${MEETME_AGI_BACKGROUND} AGI script for Meetme (zap only)
-${MEETMESECS} * Number of seconds a user participated in a MeetMe conference
+${MEETME_RECORDINGFILE} Name of file for recording a conference with
+ the "r" option
+${MEETME_RECORDINGFORMAT} Format of file to be recorded
+${MEETME_EXIT_CONTEXT} Context for exit out of meetme meeting
+${MEETME_AGI_BACKGROUND} AGI script for Meetme (zap only)
+${MEETMESECS} * Number of seconds a user participated in a MeetMe conference
+${CONF_LIMIT_TIMEOUT_FILE} File to play when time is up. Used with the L() option.
+${CONF_LIMIT_WARNING_FILE} File to play as warning if 'y' is defined.
+ The default is to say the time remaining. Used with the L() option.
\end{verbatim}
\subsection{The VoiceMail() application}