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 3 (Latest)

1 2 3
1 2 3

  1. trunk/apps/app_dial.c: Loading...
trunk/apps/app_dial.c
Revision 235739 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_debug(1,"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
	} else {

    
   
1602
		res = -1;

    
   
1603
	}

    
   
1604

   

    
   
1605
	if (ts) {

    
   
1606
		ts = ast_tone_zone_sound_unref(ts);

    
   
1607
	}

    
   
1608

   

    
   
1609
	if (res) {

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

    
   
1611
	}

    
   
1612

   

    
   
1613
	return res;

    
   
1614
}

    
   
1615

   
1579
static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast_flags64 *peerflags, int *continue_exec)
1616
static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast_flags64 *peerflags, int *continue_exec)
1580
{
1617
{
1581
	int res = -1; /* default: error */
1618
	int res = -1; /* default: error */
1582
	char *rest, *cur; /* scan the list of destinations */
1619
	char *rest, *cur; /* scan the list of destinations */
1583
	struct chanlist *outgoing = NULL; /* list of destinations */
1620
	struct chanlist *outgoing = NULL; /* list of destinations */
[+20] [20] 65 lines
[+20] static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast_flags64 *peerflags, int *continue_exec)
1649
			ast_log(LOG_WARNING, "Unknown argument %d specified to n option, ignoring\n", delprivintro);
1686
			ast_log(LOG_WARNING, "Unknown argument %d specified to n option, ignoring\n", delprivintro);
1650
			delprivintro = 0;
1687
			delprivintro = 0;
1651
		}
1688
		}
1652
	}
1689
	}
1653

    
   
1690

   

    
   
1691
	if (!ast_test_flag64(&opts, OPT_RINGBACK)) {

    
   
1692
		opt_args[OPT_ARG_RINGBACK] = NULL;

    
   
1693
	}

    
   
1694

   
1654
	if (ast_test_flag64(&opts, OPT_OPERMODE)) {
1695
	if (ast_test_flag64(&opts, OPT_OPERMODE)) {
1655
		opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
1696
		opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
1656
		ast_verb(3, "Setting operator services mode to %d.\n", opermode);
1697
		ast_verb(3, "Setting operator services mode to %d.\n", opermode);
1657
	}
1698
	}
1658

    
   
1699

   
[+20] [20] 304 lines
[+20] static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast_flags64 *peerflags, int *continue_exec)
1963
			} else {
2004
			} else {
1964
				ast_moh_start(chan, NULL, NULL);
2005
				ast_moh_start(chan, NULL, NULL);
1965
			}
2006
			}
1966
			ast_indicate(chan, AST_CONTROL_PROGRESS);
2007
			ast_indicate(chan, AST_CONTROL_PROGRESS);
1967
		} else if (ast_test_flag64(outgoing, OPT_RINGBACK)) {
2008
		} else if (ast_test_flag64(outgoing, OPT_RINGBACK)) {

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

    
   
2010
				if (dial_handle_playtones(chan, opt_args[OPT_ARG_RINGBACK])){
1968
			ast_indicate(chan, AST_CONTROL_RINGING);
2011
					ast_indicate(chan, AST_CONTROL_RINGING);
1969
			sentringing++;
2012
					sentringing++;

    
   
2013
				} else {

    
   
2014
					ast_indicate(chan, AST_CONTROL_PROGRESS);

    
   
2015
				}

    
   
2016
			} else {

    
   
2017
				ast_indicate(chan, AST_CONTROL_RINGING);

    
   
2018
				sentringing++;

    
   
2019
			}
1970
		}
2020
		}
1971
	}
2021
	}
1972

    
   
2022

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

    
   
2024

   
1975
	/* The ast_channel_datastore_remove() function could fail here if the
2025
	/* The ast_channel_datastore_remove() function could fail here if the
1976
	 * datastore was moved to another channel during a masquerade. If this is
2026
	 * 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
2027
	 * 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
2028
	 * 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.