Option to send DTMF when receiving PROGRESS status

The D() option in app_dial is only able to send DTMF after the call has been answered.  A progress option has been added to D() to allow DTMF to be sent upon receiving PROGRESS.  This allows DTMF to be sent before the call is answered.

(closes issue #12123)
Reported by: VoipForces
Patches:
	app_dial.c_patch_trunk_valid uploaded by VoipForces (license 419)
	dtmf_progress.patch uploaded by dvossel (license 671)
Tested by: VoipForces, dvossel



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@182596 65c4cc65-6c06-0410-ace0-fbb531ad65f3
certified/1.8.6
David Vossel 17 years ago
parent 9d6ba51d05
commit e559cae4ec

@ -128,6 +128,9 @@ Applications
* Added ConfBridge dialplan application which does conference bridges without * Added ConfBridge dialplan application which does conference bridges without
DAHDI. For information on its use, please see the output of DAHDI. For information on its use, please see the output of
"core show application ConfBridge" from the CLI. "core show application ConfBridge" from the CLI.
* Added progress option to the app_dial D() option. When progress DTMF is
present, those values are sent immediatly upon receiving a PROGRESS message
regardless if the call has been answered or not.
Miscellaneous Miscellaneous
------------- -------------

@ -109,11 +109,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<option name="D" argsep=":"> <option name="D" argsep=":">
<argument name="called" /> <argument name="called" />
<argument name="calling" /> <argument name="calling" />
<argument name="progress" />
<para>Send the specified DTMF strings <emphasis>after</emphasis> the called <para>Send the specified DTMF strings <emphasis>after</emphasis> the called
party has answered, but before the call gets bridged. The party has answered, but before the call gets bridged. The
<replaceable>called</replaceable> DTMF string is sent to the called party, and the <replaceable>called</replaceable> DTMF string is sent to the called party, and the
<replaceable>calling</replaceable> DTMF string is sent to the calling party. Both arguments <replaceable>calling</replaceable> DTMF string is sent to the calling party. Both arguments
can be used alone.</para> can be used alone. If <replaceable>progress</replaceable> is specified, its DTMF is sent
immediately after receiving a PROGRESS message.</para>
</option> </option>
<option name="e"> <option name="e">
<para>Execute the <literal>h</literal> extension for peer after the call ends</para> <para>Execute the <literal>h</literal> extension for peer after the call ends</para>
@ -796,7 +798,7 @@ struct privacy_args {
static struct ast_channel *wait_for_answer(struct ast_channel *in, static struct ast_channel *wait_for_answer(struct ast_channel *in,
struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags, struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags,
struct privacy_args *pa, struct privacy_args *pa,
const struct cause_args *num_in, int *result) const struct cause_args *num_in, int *result, char *dtmf_progress)
{ {
struct cause_args num = *num_in; struct cause_args num = *num_in;
int prestart = num.busy + num.congestion + num.nochan; int prestart = num.busy + num.congestion + num.nochan;
@ -952,6 +954,10 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_channel_early_bridge(in, c); ast_channel_early_bridge(in, c);
if (!ast_test_flag64(outgoing, OPT_RINGBACK)) if (!ast_test_flag64(outgoing, OPT_RINGBACK))
ast_indicate(in, AST_CONTROL_PROGRESS); ast_indicate(in, AST_CONTROL_PROGRESS);
if(!ast_strlen_zero(dtmf_progress)) {
ast_verb(3, "Sending DTMF '%s' to the called party as result of receiving a PROGRESS message.\n", dtmf_progress);
ast_dtmf_stream(c, in, dtmf_progress, 250, 0);
}
break; break;
case AST_CONTROL_VIDUPDATE: case AST_CONTROL_VIDUPDATE:
ast_verb(3, "%s requested a video update, passing it to %s\n", c->name, in->name); ast_verb(3, "%s requested a video update, passing it to %s\n", c->name, in->name);
@ -1502,7 +1508,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
struct ast_bridge_config config = { { 0, } }; struct ast_bridge_config config = { { 0, } };
struct timeval calldurationlimit = { 0, }; struct timeval calldurationlimit = { 0, };
char *dtmfcalled = NULL, *dtmfcalling = NULL; char *dtmfcalled = NULL, *dtmfcalling = NULL, *dtmf_progress=NULL;
struct privacy_args pa = { struct privacy_args pa = {
.sentringing = 0, .sentringing = 0,
.privdb_val = 0, .privdb_val = 0,
@ -1553,7 +1559,6 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
goto done; goto done;
} }
if (ast_test_flag64(&opts, OPT_OPERMODE)) { if (ast_test_flag64(&opts, OPT_OPERMODE)) {
opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]); opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
ast_verb(3, "Setting operator services mode to %d.\n", opermode); ast_verb(3, "Setting operator services mode to %d.\n", opermode);
@ -1570,8 +1575,9 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
} }
if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) { if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
dtmfcalling = opt_args[OPT_ARG_SENDDTMF]; dtmf_progress = opt_args[OPT_ARG_SENDDTMF];
dtmfcalled = strsep(&dtmfcalling, ":"); dtmfcalled = strsep(&dtmf_progress, ":");
dtmfcalling = strsep(&dtmf_progress, ":");
} }
if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) { if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
@ -1838,7 +1844,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
} }
} }
peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result); peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result, dtmf_progress);
/* The ast_channel_datastore_remove() function could fail here if the /* The ast_channel_datastore_remove() function could fail here if the
* datastore was moved to another channel during a masquerade. If this is * datastore was moved to another channel during a masquerade. If this is

Loading…
Cancel
Save