From 7537d3c0cb09bccf6e2a15a2ba2f6f195be268d6 Mon Sep 17 00:00:00 2001 From: Alec L Davis <sivad.a@paradise.net.nz> Date: Sat, 19 Dec 2009 08:59:31 +0000 Subject: [PATCH] app_dial optional parameter to option 'r' to allow play indication from indications.conf (closes issue #14504) Reported by: alecdavis Tested by: alecdavis,jsmith Patch app_dial.play_ring_indications.diff7.txt uploaded by alecdavis (license 585) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@235740 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- CHANGES | 2 ++ apps/app_dial.c | 70 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 39bd92398d..74f20fbb78 100644 --- a/CHANGES +++ b/CHANGES @@ -82,6 +82,8 @@ Applications announcements or macros are executed. * Modified app_dial to set answertime when the called channel answers even if the called channel hangs up during playback of an announcement. + * Modified app_dial 'r' option to support an additional parameter to play an + indication tone from indications.conf * Added c() option to app_chanspy. This option allows custom DTMF to be set to cycle through the next available channel. By default this is still '*'. * Added x() option to app_chanspy. This option allows DTMF to be set to diff --git a/apps/app_dial.c b/apps/app_dial.c index 0ef64b3cc2..c24a566472 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -62,6 +62,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/global_datastores.h" #include "asterisk/dsp.h" #include "asterisk/cel.h" +#include "asterisk/indications.h" /*** DOCUMENTATION <application name="Dial" language="en_US"> @@ -319,8 +320,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") it is provided. The current extension is used if a database family/key is not specified.</para> </option> <option name="r"> - <para>Indicate ringing to the calling party, even if the called party isn't actually ringing. Pass no audio to the calling + <para>Default: Indicate ringing to the calling party, even if the called party isn't actually ringing. Pass no audio to the calling party until the called channel has answered.</para> + <argument name="tone" required="false"> + <para>Indicate progress to calling party. Send audio 'tone' from indications.conf</para> + </argument> </option> <option name="S"> <argument name="x" required="true" /> @@ -535,6 +539,7 @@ enum { OPT_ARG_DURATION_LIMIT, OPT_ARG_MUSICBACK, OPT_ARG_CALLEE_MACRO, + OPT_ARG_RINGBACK, OPT_ARG_CALLEE_GOSUB, OPT_ARG_CALLEE_GO_ON, OPT_ARG_PRIVACY, @@ -572,7 +577,7 @@ AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS AST_APP_OPTION_ARG('O', OPT_OPERMODE, OPT_ARG_OPERMODE), AST_APP_OPTION('p', OPT_SCREENING), AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY), - AST_APP_OPTION('r', OPT_RINGBACK), + AST_APP_OPTION_ARG('r', OPT_RINGBACK, OPT_ARG_RINGBACK), AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP), AST_APP_OPTION('t', OPT_CALLEE_TRANSFER), AST_APP_OPTION('T', OPT_CALLER_TRANSFER), @@ -890,6 +895,7 @@ struct privacy_args { static struct ast_channel *wait_for_answer(struct ast_channel *in, struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags, + char *opt_args[], struct privacy_args *pa, const struct cause_args *num_in, int *result, char *dtmf_progress) { @@ -908,11 +914,12 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, ast_party_connected_line_init(&connected_caller); if (single) { /* Turn off hold music, etc */ - if (!ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK)) + if (!ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK)) { ast_deactivate_generator(in); - - /* If we are calling a single channel, make them compatible for in-band tone purpose */ - ast_channel_make_compatible(outgoing->chan, in); + /* If we are calling a single channel, and not providing ringback or music, */ + /* then, make them compatible for in-band tone purpose */ + ast_channel_make_compatible(outgoing->chan, in); + } if (!ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE) && !ast_test_flag64(outgoing, DIAL_NOCONNECTEDLINE)) { ast_channel_lock(outgoing->chan); @@ -1078,7 +1085,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, /* Setup early media if appropriate */ if (single && CAN_EARLY_BRIDGE(peerflags, in, c)) ast_channel_early_bridge(in, c); - if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK)) { + if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK) && ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) { ast_indicate(in, AST_CONTROL_RINGING); pa->sentringing++; } @@ -1576,6 +1583,36 @@ static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, st bconfig->end_bridge_callback_data = originator; } +static int dial_handle_playtones(struct ast_channel *chan, const char *data) +{ + struct ast_tone_zone_sound *ts = NULL; + int res; + const char *str = data; + + if (ast_strlen_zero(str)) { + ast_debug(1,"Nothing to play\n"); + return -1; + } + + ts = ast_get_indication_tone(chan->zone, str); + + if (ts && ts->data[0]) { + res = ast_playtones_start(chan, 0, ts->data, 0); + } else { + res = -1; + } + + if (ts) { + ts = ast_tone_zone_sound_unref(ts); + } + + if (res) { + ast_log(LOG_WARNING, "Unable to start playtone \'%s\'\n", str); + } + + return res; +} + static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast_flags64 *peerflags, int *continue_exec) { int res = -1; /* default: error */ @@ -1651,6 +1688,10 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast } } + if (!ast_test_flag64(&opts, OPT_RINGBACK)) { + opt_args[OPT_ARG_RINGBACK] = NULL; + } + if (ast_test_flag64(&opts, OPT_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); @@ -1965,12 +2006,21 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast } ast_indicate(chan, AST_CONTROL_PROGRESS); } else if (ast_test_flag64(outgoing, OPT_RINGBACK)) { - ast_indicate(chan, AST_CONTROL_RINGING); - sentringing++; + if (!ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) { + if (dial_handle_playtones(chan, opt_args[OPT_ARG_RINGBACK])){ + ast_indicate(chan, AST_CONTROL_RINGING); + sentringing++; + } else { + ast_indicate(chan, AST_CONTROL_PROGRESS); + } + } else { + ast_indicate(chan, AST_CONTROL_RINGING); + sentringing++; + } } } - peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result, dtmf_progress); + peer = wait_for_answer(chan, outgoing, &to, peerflags, opt_args, &pa, &num, &result, dtmf_progress); /* The ast_channel_datastore_remove() function could fail here if the * datastore was moved to another channel during a masquerade. If this is -- GitLab