From 1ae31fd2a9d02857f6915778e528e81c77540543 Mon Sep 17 00:00:00 2001 From: Richard Mudgett Date: Tue, 15 May 2012 16:53:09 +0000 Subject: Add predial support to FollowMe. Like the new predial feature for Dial. This adds the same b/B options to FollowMe. Review: https://reviewboard.asterisk.org/r/1910/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@366507 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_followme.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) (limited to 'apps/app_followme.c') diff --git a/apps/app_followme.c b/apps/app_followme.c index bbbde5fab..f44d453ad 100644 --- a/apps/app_followme.c +++ b/apps/app_followme.c @@ -71,6 +71,27 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") Record the caller's name so it can be announced to the callee on each step. + + @@ -155,6 +176,8 @@ struct call_followme { struct fm_args { char *mohclass; AST_LIST_HEAD_NOLOCK(cnumbers, number) cnumbers; + /*! Gosub app arguments for outgoing calls. NULL if not supplied. */ + const char *predial_callee; /*! Accumulated connected line information from inbound call. */ struct ast_party_connected_line connected_in; /*! Accumulated connected line information from outbound call. */ @@ -205,10 +228,22 @@ enum { FOLLOWMEFLAG_NOANSWER = (1 << 4), FOLLOWMEFLAG_DISABLEOPTIMIZATION = (1 << 5), FOLLOWMEFLAG_IGNORE_CONNECTEDLINE = (1 << 6), + FOLLOWMEFLAG_PREDIAL_CALLER = (1 << 7), + FOLLOWMEFLAG_PREDIAL_CALLEE = (1 << 8), +}; + +enum { + FOLLOWMEFLAG_ARG_PREDIAL_CALLER, + FOLLOWMEFLAG_ARG_PREDIAL_CALLEE, + + /* note: this entry _MUST_ be the last one in the enum */ + FOLLOWMEFLAG_ARG_ARRAY_SIZE }; AST_APP_OPTIONS(followme_opts, { AST_APP_OPTION('a', FOLLOWMEFLAG_RECORDNAME), + AST_APP_OPTION_ARG('B', FOLLOWMEFLAG_PREDIAL_CALLER, FOLLOWMEFLAG_ARG_PREDIAL_CALLER), + AST_APP_OPTION_ARG('b', FOLLOWMEFLAG_PREDIAL_CALLEE, FOLLOWMEFLAG_ARG_PREDIAL_CALLEE), AST_APP_OPTION('d', FOLLOWMEFLAG_DISABLEHOLDPROMPT), AST_APP_OPTION('I', FOLLOWMEFLAG_IGNORE_CONNECTEDLINE), AST_APP_OPTION('l', FOLLOWMEFLAG_DISABLEOPTIMIZATION), @@ -1044,6 +1079,48 @@ static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel AST_LIST_INSERT_TAIL(&new_user_list, tmpuser, entry); } + /* + * PREDIAL: Run gosub on all of the new callee channels + * + * We run the callee predial before ast_call() in case the user + * wishes to do something on the newly created channels before + * the channel does anything important. + */ + if (tpargs->predial_callee && !AST_LIST_EMPTY(&new_user_list)) { + /* Put caller into autoservice. */ + ast_autoservice_start(caller); + + /* Run predial on all new outgoing calls. */ + AST_LIST_TRAVERSE(&new_user_list, tmpuser, entry) { + ast_pre_call(tmpuser->ochan, tpargs->predial_callee); + } + + /* Take caller out of autoservice. */ + if (ast_autoservice_stop(caller)) { + /* + * Caller hungup. + * + * Destoy all new outgoing calls. + */ + while ((tmpuser = AST_LIST_REMOVE_HEAD(&new_user_list, entry))) { + ast_channel_lock(tmpuser->ochan); + if (ast_channel_cdr(tmpuser->ochan)) { + ast_cdr_init(ast_channel_cdr(tmpuser->ochan), tmpuser->ochan); + } + ast_channel_unlock(tmpuser->ochan); + destroy_calling_node(tmpuser); + } + + /* Take all active outgoing channels out of autoservice. */ + AST_LIST_TRAVERSE(&findme_user_list, tmpuser, entry) { + if (tmpuser->ochan) { + ast_autoservice_stop(tmpuser->ochan); + } + } + break; + } + } + /* Start all new outgoing calls */ AST_LIST_TRAVERSE_SAFE_BEGIN(&new_user_list, tmpuser, entry) { ast_verb(3, "calling Local/%s\n", tmpuser->dialarg); @@ -1237,6 +1314,7 @@ static int app_exec(struct ast_channel *chan, const char *data) AST_APP_ARG(followmeid); AST_APP_ARG(options); ); + char *opt_args[FOLLOWMEFLAG_ARG_ARRAY_SIZE]; if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "%s requires an argument (followmeid)\n", app); @@ -1278,7 +1356,7 @@ static int app_exec(struct ast_channel *chan, const char *data) /* XXX TODO: Reinsert the db check value to see whether or not follow-me is on or off */ if (args.options) { - ast_app_parse_options(followme_opts, &targs->followmeflags, NULL, args.options); + ast_app_parse_options(followme_opts, &targs->followmeflags, opt_args, args.options); } /* Lock the profile lock and copy out everything we need to run with before unlocking it again */ @@ -1304,6 +1382,20 @@ static int app_exec(struct ast_channel *chan, const char *data) } ast_mutex_unlock(&f->lock); + /* PREDIAL: Preprocess any callee gosub arguments. */ + if (ast_test_flag(&targs->followmeflags, FOLLOWMEFLAG_PREDIAL_CALLEE) + && !ast_strlen_zero(opt_args[FOLLOWMEFLAG_ARG_PREDIAL_CALLEE])) { + ast_replace_subargument_delimiter(opt_args[FOLLOWMEFLAG_ARG_PREDIAL_CALLEE]); + targs->predial_callee = opt_args[FOLLOWMEFLAG_ARG_PREDIAL_CALLEE]; + } + + /* PREDIAL: Run gosub on the caller's channel */ + if (ast_test_flag(&targs->followmeflags, FOLLOWMEFLAG_PREDIAL_CALLER) + && !ast_strlen_zero(opt_args[FOLLOWMEFLAG_ARG_PREDIAL_CALLER])) { + ast_replace_subargument_delimiter(opt_args[FOLLOWMEFLAG_ARG_PREDIAL_CALLER]); + ast_app_exec_sub(NULL, chan, opt_args[FOLLOWMEFLAG_ARG_PREDIAL_CALLER]); + } + /* Forget the 'N' option if the call is already up. */ if (ast_channel_state(chan) == AST_STATE_UP) { ast_clear_flag(&targs->followmeflags, FOLLOWMEFLAG_NOANSWER); -- cgit v1.2.3