diff options
-rw-r--r-- | CHANGES | 6 | ||||
-rw-r--r-- | apps/app_meetme.c | 188 | ||||
-rw-r--r-- | doc/tex/channelvariables.tex | 15 |
3 files changed, 195 insertions, 14 deletions
@@ -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} |