Review Board 1.7.16


Allow app_dial to play 'indication tone while ringing' like 'option m' which will provide music on hold while ringing

Review Request #448 - Created Dec. 15, 2009 and submitted

Alec Davis
trunk
14504
Reviewers
asterisk-dev
Asterisk
This senario is based on an ETSI ISDN installation, but I'm sure applies to others.

option 'r' sends a Ringing Indication to the network, which informs the network we can deliver the call, but ultimately we may not be able to, and need to issue Congestion.
option 'm' sends a Progress Indication, which allows us to indicate Congestion and then let the call go, the network providor can then try the next provider.

The current ugly solution, is to record a music file, of Ringing, and play it, something like.
  exten => 80,1,Dial(DAHDI/2,30,m(myring))
  exten => 80,n,Congestion()

This patch provides an optional argument for option 'r' as in 'r(vodaring)'

Now a tidy and customizable way to play out any tones from the indications.conf file like.
  exten => 80,1,Dial(DAHDI/2,30,r(vodaring))
  exten => 80,n,Congestion()
100% test results with examples below.

exten => 80,1,Dial(DAHDI/2,,r(vodaring))
exten => 80,1,Dial(DAHDI/2,,r)
exten => 80,1,Dial(DAHDI/2,,m)
exten => 80,1,Dial(DAHDI/2,,)

Diff revision 1

This is not the most recent revision of the diff. The latest diff is revision 3. See what's changed.

1 2 3
1 2 3

  1. trunk/apps/app_dial.c: Loading...
trunk/apps/app_dial.c
Revision 231431 New Change
[20] 59 lines
[+20] [+] ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
60
#include "asterisk/privacy.h"
60
#include "asterisk/privacy.h"
61
#include "asterisk/stringfields.h"
61
#include "asterisk/stringfields.h"
62
#include "asterisk/global_datastores.h"
62
#include "asterisk/global_datastores.h"
63
#include "asterisk/dsp.h"
63
#include "asterisk/dsp.h"
64
#include "asterisk/cel.h"
64
#include "asterisk/cel.h"

    
   
65
#include "asterisk/indications.h"
65

    
   
66

   
66
/*** DOCUMENTATION
67
/*** DOCUMENTATION
67
	<application name="Dial" language="en_US">
68
	<application name="Dial" language="en_US">
68
		<synopsis>
69
		<synopsis>
69
			Attempt to connect to another device or endpoint and bridge the call.
70
			Attempt to connect to another device or endpoint and bridge the call.
[+20] [20] 247 lines
[+20] ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
317
					<argument name="x" />
318
					<argument name="x" />
318
					<para>Enable privacy mode. Use <replaceable>x</replaceable> as the family/key in the AstDB database if
319
					<para>Enable privacy mode. Use <replaceable>x</replaceable> as the family/key in the AstDB database if
319
					it is provided. The current extension is used if a database family/key is not specified.</para>
320
					it is provided. The current extension is used if a database family/key is not specified.</para>
320
				</option>
321
				</option>
321
				<option name="r">
322
				<option name="r">
322
					<para>Indicate ringing to the calling party, even if the called party isn't actually ringing. Pass no audio to the calling
323
					<para>Default: Indicate ringing to the calling party, even if the called party isn't actually ringing. Pass no audio to the calling
323
					party until the called channel has answered.</para>
324
					party until the called channel has answered.</para>

    
   
325
					<argument name="tone" required="false">

    
   
326
						<para>Indicate progress to calling party. Send audio 'tone' from indications.conf</para>

    
   
327
					</argument>
324
				</option>
328
				</option>
325
				<option name="S">
329
				<option name="S">
326
					<argument name="x" required="true" />
330
					<argument name="x" required="true" />
327
					<para>Hang up the call <replaceable>x</replaceable> seconds <emphasis>after</emphasis> the called party has
331
					<para>Hang up the call <replaceable>x</replaceable> seconds <emphasis>after</emphasis> the called party has
328
					answered the call.</para>
332
					answered the call.</para>
[+20] [20] 204 lines
[+20] [+] enum {
533
	OPT_ARG_SENDDTMF,
537
	OPT_ARG_SENDDTMF,
534
	OPT_ARG_GOTO,
538
	OPT_ARG_GOTO,
535
	OPT_ARG_DURATION_LIMIT,
539
	OPT_ARG_DURATION_LIMIT,
536
	OPT_ARG_MUSICBACK,
540
	OPT_ARG_MUSICBACK,
537
	OPT_ARG_CALLEE_MACRO,
541
	OPT_ARG_CALLEE_MACRO,

    
   
542
	OPT_ARG_RINGBACK,
538
	OPT_ARG_CALLEE_GOSUB,
543
	OPT_ARG_CALLEE_GOSUB,
539
	OPT_ARG_CALLEE_GO_ON,
544
	OPT_ARG_CALLEE_GO_ON,
540
	OPT_ARG_PRIVACY,
545
	OPT_ARG_PRIVACY,
541
	OPT_ARG_DURATION_STOP,
546
	OPT_ARG_DURATION_STOP,
542
	OPT_ARG_OPERMODE,
547
	OPT_ARG_OPERMODE,
[+20] [20] 27 lines
[+20] [+] AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
570
	AST_APP_OPTION('N', OPT_SCREEN_NOCALLERID),
575
	AST_APP_OPTION('N', OPT_SCREEN_NOCALLERID),
571
	AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
576
	AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
572
	AST_APP_OPTION_ARG('O', OPT_OPERMODE, OPT_ARG_OPERMODE),
577
	AST_APP_OPTION_ARG('O', OPT_OPERMODE, OPT_ARG_OPERMODE),
573
	AST_APP_OPTION('p', OPT_SCREENING),
578
	AST_APP_OPTION('p', OPT_SCREENING),
574
	AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
579
	AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
575
	AST_APP_OPTION('r', OPT_RINGBACK),
580
	AST_APP_OPTION_ARG('r', OPT_RINGBACK, OPT_ARG_RINGBACK),
576
	AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
581
	AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
577
	AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
582
	AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
578
	AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
583
	AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
579
	AST_APP_OPTION_ARG('U', OPT_CALLEE_GOSUB, OPT_ARG_CALLEE_GOSUB),
584
	AST_APP_OPTION_ARG('U', OPT_CALLEE_GOSUB, OPT_ARG_CALLEE_GOSUB),
580
	AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
585
	AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
[+20] [20] 307 lines
[+20] [+] struct privacy_args {
888
	char status[256];
893
	char status[256];
889
};
894
};
890

    
   
895

   
891
static struct ast_channel *wait_for_answer(struct ast_channel *in,
896
static struct ast_channel *wait_for_answer(struct ast_channel *in,
892
	struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags,
897
	struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags,

    
   
898
	char *opt_args[],
893
	struct privacy_args *pa,
899
	struct privacy_args *pa,
894
	const struct cause_args *num_in, int *result, char *dtmf_progress)
900
	const struct cause_args *num_in, int *result, char *dtmf_progress)
895
{
901
{
896
	struct cause_args num = *num_in;
902
	struct cause_args num = *num_in;
897
	int prestart = num.busy + num.congestion + num.nochan;
903
	int prestart = num.busy + num.congestion + num.nochan;
[+20] [20] 8 lines
[+20] static struct ast_channel *wait_for_answer(struct ast_channel *in,
906
	struct ast_str *featurecode = ast_str_alloca(FEATURE_MAX_LEN + 1);
912
	struct ast_str *featurecode = ast_str_alloca(FEATURE_MAX_LEN + 1);
907

    
   
913

   
908
	ast_party_connected_line_init(&connected_caller);
914
	ast_party_connected_line_init(&connected_caller);
909
	if (single) {
915
	if (single) {
910
		/* Turn off hold music, etc */
916
		/* Turn off hold music, etc */
911
		if (!ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK))
917
		if (!ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK)) {
912
			ast_deactivate_generator(in);
918
			ast_deactivate_generator(in);
913

    
   
919
			/* If we are calling a single channel, and not providing ringback or music, */
914
		/* If we are calling a single channel, make them compatible for in-band tone purpose */
920
			/* then, make them compatible for in-band tone purpose */
915
		ast_channel_make_compatible(outgoing->chan, in);
921
			ast_channel_make_compatible(outgoing->chan, in);

    
   
922
		}
916

    
   
923

   
917
		if (!ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE) && !ast_test_flag64(outgoing, DIAL_NOCONNECTEDLINE)) {
924
		if (!ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE) && !ast_test_flag64(outgoing, DIAL_NOCONNECTEDLINE)) {
918
			ast_channel_lock(outgoing->chan);
925
			ast_channel_lock(outgoing->chan);
919
			ast_connected_line_copy_from_caller(&connected_caller, &outgoing->chan->cid);
926
			ast_connected_line_copy_from_caller(&connected_caller, &outgoing->chan->cid);
920
			ast_channel_unlock(outgoing->chan);
927
			ast_channel_unlock(outgoing->chan);
[+20] [20] 155 lines
[+20] static struct ast_channel *wait_for_answer(struct ast_channel *in,
1076
				case AST_CONTROL_RINGING:
1083
				case AST_CONTROL_RINGING:
1077
					ast_verb(3, "%s is ringing\n", c->name);
1084
					ast_verb(3, "%s is ringing\n", c->name);
1078
					/* Setup early media if appropriate */
1085
					/* Setup early media if appropriate */
1079
					if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
1086
					if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
1080
						ast_channel_early_bridge(in, c);
1087
						ast_channel_early_bridge(in, c);
1081
					if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK)) {
1088
					if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK) && ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) {
1082
						ast_indicate(in, AST_CONTROL_RINGING);
1089
						ast_indicate(in, AST_CONTROL_RINGING);
1083
						pa->sentringing++;
1090
						pa->sentringing++;
1084
					}
1091
					}
1085
					break;
1092
					break;
1086
				case AST_CONTROL_PROGRESS:
1093
				case AST_CONTROL_PROGRESS:
[+20] [20] 487 lines
[+20] [+] static void end_bridge_callback(void *data)
1574

    
   
1581

   
1575
static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator) {
1582
static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator) {
1576
	bconfig->end_bridge_callback_data = originator;
1583
	bconfig->end_bridge_callback_data = originator;
1577
}
1584
}
1578

    
   
1585

   

    
   
1586
static int dial_handle_playtones(struct ast_channel *chan, const char *data)

    
   
1587
{

    
   
1588
	struct ast_tone_zone_sound *ts = NULL;

    
   
1589
	int res;

    
   
1590
	const char *str = data;

    
   
1591

   

    
   
1592
	if (ast_strlen_zero(str)) {

    
   
1593
		ast_log(LOG_NOTICE,"Nothing to play\n");

    
   
1594
		return -1;

    
   
1595
	}

    
   
1596

   

    
   
1597
	ts = ast_get_indication_tone(chan->zone, str);

    
   
1598

   

    
   
1599
	if (ts && ts->data[0]) {

    
   
1600
		res = ast_playtones_start(chan, 0, ts->data, 0);

    
   
1601
		ts = ast_tone_zone_sound_unref(ts);

    
   
1602
	} else {

    
   
1603
		res = -1;

    
   
1604
	}

    
   
1605

   

    
   
1606
	if (res) {

    
   
1607
		ast_log(LOG_NOTICE, "Unable to start playtone \'%s\'\n", str);

    
   
1608
	}

    
   
1609

   

    
   
1610
	return res;

    
   
1611
}

    
   
1612

   
1579
static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast_flags64 *peerflags, int *continue_exec)
1613
static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast_flags64 *peerflags, int *continue_exec)
1580
{
1614
{
1581
	int res = -1; /* default: error */
1615
	int res = -1; /* default: error */
1582
	char *rest, *cur; /* scan the list of destinations */
1616
	char *rest, *cur; /* scan the list of destinations */
1583
	struct chanlist *outgoing = NULL; /* list of destinations */
1617
	struct chanlist *outgoing = NULL; /* list of destinations */
[+20] [20] 379 lines
[+20] static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast_flags64 *peerflags, int *continue_exec)
1963
			} else {
1997
			} else {
1964
				ast_moh_start(chan, NULL, NULL);
1998
				ast_moh_start(chan, NULL, NULL);
1965
			}
1999
			}
1966
			ast_indicate(chan, AST_CONTROL_PROGRESS);
2000
			ast_indicate(chan, AST_CONTROL_PROGRESS);
1967
		} else if (ast_test_flag64(outgoing, OPT_RINGBACK)) {
2001
		} else if (ast_test_flag64(outgoing, OPT_RINGBACK)) {

    
   
2002
			if (!ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) {

    
   
2003
				if (dial_handle_playtones(chan, opt_args[OPT_ARG_RINGBACK])){
1968
			ast_indicate(chan, AST_CONTROL_RINGING);
2004
					ast_indicate(chan, AST_CONTROL_RINGING);
1969
			sentringing++;
2005
					sentringing++;

    
   
2006
				} else {

    
   
2007
					ast_indicate(chan, AST_CONTROL_PROGRESS);

    
   
2008
				}

    
   
2009
			} else {

    
   
2010
				ast_indicate(chan, AST_CONTROL_RINGING);

    
   
2011
				sentringing++;

    
   
2012
			}
1970
		}
2013
		}
1971
	}
2014
	}
1972

    
   
2015

   
1973
	peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result, dtmf_progress);
2016
	peer = wait_for_answer(chan, outgoing, &to, peerflags, opt_args, &pa, &num, &result, dtmf_progress);
1974

    
   
2017

   
1975
	/* The ast_channel_datastore_remove() function could fail here if the
2018
	/* The ast_channel_datastore_remove() function could fail here if the
1976
	 * datastore was moved to another channel during a masquerade. If this is
2019
	 * datastore was moved to another channel during a masquerade. If this is
1977
	 * the case, don't free the datastore here because later, when the channel
2020
	 * the case, don't free the datastore here because later, when the channel
1978
	 * to which the datastore was moved hangs up, it will attempt to free this
2021
	 * to which the datastore was moved hangs up, it will attempt to free this
[+20] [20] 617 lines
  1. trunk/apps/app_dial.c: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.