</parameter>
<parameter name="options">
<optionlist>
+ <option name="b" argsep="^">
+ <para>Before initiating an outgoing call, Gosub to the specified
+ location using the newly created channel. The Gosub will be
+ executed for each destination channel.</para>
+ <argument name="context" required="false" />
+ <argument name="exten" required="false" />
+ <argument name="priority" required="true" hasparams="optional" argsep="^">
+ <argument name="arg1" multiple="true" required="true" />
+ <argument name="argN" />
+ </argument>
+ </option>
+ <option name="B" argsep="^">
+ <para>Before initiating the outgoing call(s), Gosub to the specified
+ location using the current channel.</para>
+ <argument name="context" required="false" />
+ <argument name="exten" required="false" />
+ <argument name="priority" required="true" hasparams="optional" argsep="^">
+ <argument name="arg1" multiple="true" required="true" />
+ <argument name="argN" />
+ </argument>
+ </option>
<option name="d">
<para>Full duplex audio</para>
</option>
PAGE_IGNORE_FORWARDS = (1 << 4),
PAGE_ANNOUNCE = (1 << 5),
PAGE_NOCALLERANNOUNCE = (1 << 6),
+ PAGE_PREDIAL_CALLEE = (1 << 7),
+ PAGE_PREDIAL_CALLER = (1 << 8),
};
enum {
OPT_ARG_ANNOUNCE = 0,
- OPT_ARG_ARRAY_SIZE = 1,
+ OPT_ARG_PREDIAL_CALLEE = 1,
+ OPT_ARG_PREDIAL_CALLER = 2,
+ OPT_ARG_ARRAY_SIZE = 3,
};
AST_APP_OPTIONS(page_opts, {
+ AST_APP_OPTION_ARG('b', PAGE_PREDIAL_CALLEE, OPT_ARG_PREDIAL_CALLEE),
+ AST_APP_OPTION_ARG('B', PAGE_PREDIAL_CALLER, OPT_ARG_PREDIAL_CALLER),
AST_APP_OPTION('d', PAGE_DUPLEX),
AST_APP_OPTION('q', PAGE_QUIET),
AST_APP_OPTION('r', PAGE_RECORD),
return -1;
}
+ if (ast_test_flag(&options.flags, PAGE_PREDIAL_CALLER)
+ && !ast_strlen_zero(options.opts[OPT_ARG_PREDIAL_CALLER])) {
+ ast_replace_subargument_delimiter(options.opts[OPT_ARG_PREDIAL_CALLER]);
+ ast_app_exec_sub(NULL, chan, options.opts[OPT_ARG_PREDIAL_CALLER], 0);
+ }
+
/* Go through parsing/calling each device */
while ((tech = strsep(&args.devices, "&"))) {
int state = 0;
/* Set ANSWER_EXEC as global option */
ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, confbridgeopts);
+ if (ast_test_flag(&options.flags, PAGE_PREDIAL_CALLEE)
+ && !ast_strlen_zero(options.opts[OPT_ARG_PREDIAL_CALLEE])) {
+ ast_dial_option_global_enable(dial, AST_DIAL_OPTION_PREDIAL, options.opts[OPT_ARG_PREDIAL_CALLEE]);
+ }
+
if (timeout) {
ast_dial_set_global_timeout(dial, timeout * 1000);
}
return 0;
}
+static void *predial_enable(void *data)
+{
+ return ast_strdup(data);
+}
+
+static int predial_disable(void *data)
+{
+ if (!data) {
+ return -1;
+ }
+
+ ast_free(data);
+
+ return 0;
+}
+
/*! \brief Application execution function for 'ANSWER_EXEC' option */
static void answer_exec_run(struct ast_dial *dial, struct ast_dial_channel *dial_channel, char *app, char *args)
{
{ AST_DIAL_OPTION_ANSWER_EXEC, answer_exec_enable, answer_exec_disable }, /*!< Execute application upon answer in async mode */
{ AST_DIAL_OPTION_MUSIC, music_enable, music_disable }, /*!< Play music to the caller instead of ringing */
{ AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, NULL, NULL }, /*!< Disable call forwarding on channels */
+ { AST_DIAL_OPTION_PREDIAL, predial_enable, predial_disable }, /*!< Execute a subroutine on the outbound channels prior to dialing */
{ AST_DIAL_OPTION_MAX, NULL, NULL }, /*!< Terminator of list */
};
}
/*! \brief Helper function that requests all channels */
-static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channel *chan, struct ast_format_cap *cap)
+static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channel *chan, struct ast_format_cap *cap, const char *predial_string)
{
char numsubst[AST_MAX_EXTENSION];
struct ast_format_cap *cap_all_audio = NULL;
ast_channel_stage_snapshot_done(channel->owner);
+ if (!ast_strlen_zero(predial_string)) {
+ const char *predial_callee = ast_app_expand_sub_args(chan, predial_string);
+ if (!predial_callee) {
+ ast_log(LOG_ERROR, "Could not expand subroutine arguments in predial request '%s'\n", predial_string);
+ }
+ ast_autoservice_start(chan);
+ ast_pre_call(channel->owner, predial_callee);
+ ast_autoservice_stop(chan);
+ ast_free((char *) predial_callee);
+ }
+
return 0;
}
{
struct ast_dial_channel *channel;
int res = -1;
+ char *predial_string = dial->options[AST_DIAL_OPTION_PREDIAL];
+
+ if (!ast_strlen_zero(predial_string)) {
+ ast_replace_subargument_delimiter(predial_string);
+ }
AST_LIST_LOCK(&dial->channels);
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
- if ((res = begin_dial_prerun(channel, chan, cap))) {
+ if ((res = begin_dial_prerun(channel, chan, cap, predial_string))) {
break;
}
}
}
/*! \brief Helper function that does the beginning dialing per-appended channel */
-static int begin_dial_channel(struct ast_dial_channel *channel, struct ast_channel *chan, int async)
+static int begin_dial_channel(struct ast_dial_channel *channel, struct ast_channel *chan, int async, const char *predial_string)
{
char numsubst[AST_MAX_EXTENSION];
int res = 1;
/* If no owner channel exists yet execute pre-run */
- if (!channel->owner && begin_dial_prerun(channel, chan, NULL)) {
+ if (!channel->owner && begin_dial_prerun(channel, chan, NULL, predial_string)) {
return 0;
}
{
struct ast_dial_channel *channel = NULL;
int success = 0;
+ char *predial_string = dial->options[AST_DIAL_OPTION_PREDIAL];
+
+ if (!ast_strlen_zero(predial_string)) {
+ ast_replace_subargument_delimiter(predial_string);
+ }
/* Iterate through channel list, requesting and calling each one */
AST_LIST_LOCK(&dial->channels);
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
- success += begin_dial_channel(channel, chan, async);
+ success += begin_dial_channel(channel, chan, async, predial_string);
}
AST_LIST_UNLOCK(&dial->channels);
struct ast_channel *original = channel->owner;
char *tmp = ast_strdupa(ast_channel_call_forward(channel->owner));
char *tech = "Local", *device = tmp, *stuff;
+ char *predial_string = dial->options[AST_DIAL_OPTION_PREDIAL];
+
+ if (!ast_strlen_zero(predial_string)) {
+ ast_replace_subargument_delimiter(predial_string);
+ }
/* If call forwarding is disabled just drop the original channel and don't attempt to dial the new one */
if (FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_DISABLE_CALL_FORWARDING)) {
channel->owner = NULL;
/* Finally give it a go... send it out into the world */
- begin_dial_channel(channel, chan, chan ? 0 : 1);
+ begin_dial_channel(channel, chan, chan ? 0 : 1, predial_string);
return 0;
}