[Asterisk-code-review] sig_analog: Add Call Waiting Deluxe support. (asterisk[master])
N A
asteriskteam at digium.com
Thu Dec 22 09:57:03 CST 2022
N A has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/19748 )
Change subject: sig_analog: Add Call Waiting Deluxe support.
......................................................................
sig_analog: Add Call Waiting Deluxe support.
Adds support for Call Waiting Deluxe options to enhance
the current call waiting feature.
As part of this change, a mechanism is also added that
allows a channel driver to queue an audio file for Dial()
to play, which is necessary for the announcement function.
ASTERISK-30373 #close
Change-Id: Ifd222b5f757c8dd382158a89c6b6ad9a82b07421
---
M apps/app_dial.c
M channels/chan_dahdi.c
M channels/chan_dahdi.h
M channels/sig_analog.c
M channels/sig_analog.h
M configs/samples/chan_dahdi.conf.sample
A doc/CHANGES-staging/callwaitingdeluxe.txt
M include/asterisk/channel.h
M main/channel_internal_api.c
9 files changed, 309 insertions(+), 0 deletions(-)
git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/48/19748/1
diff --git a/apps/app_dial.c b/apps/app_dial.c
index c389225..c09c61d 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -1417,6 +1417,10 @@
}
}
continue;
+ } else if (!ast_strlen_zero(ast_channel_dial_announcement(c))) {
+ ast_verb(3, "Playing audio file %s on %s\n", ast_channel_dial_announcement(c), ast_channel_name(in));
+ ast_streamfile(in, ast_channel_dial_announcement(c), ast_channel_language(in));
+ ast_channel_dial_announcement_set(c, ""); /* Don't set to NULL, that will cause a crash */
}
f = ast_read(winner);
if (!f) {
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 5607eb0..ca75633 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -9071,6 +9071,26 @@
return -1;
}
+ if (p->sig == SIG_FXOLS || p->sig == SIG_FXOKS || p->sig == SIG_FXOGS) {
+ struct analog_pvt *analog_p = p->sig_pvt;
+ if (analog_p->callwaitdeluxepending) {
+ unsigned int mssinceflash = ast_tvdiff_ms(ast_tvnow(), analog_p->flashtime);
+ if (mssinceflash >= 1000) {
+ /* Timer expired: the user hasn't yet selected an option. Take the default action and get on with it. */
+ /* Note: If in the future Advanced Call Waiting Deluxe (*76) is supported, then as part of the
+ * dialing code, we'll need to automatically invoke the preselected behavior about 2-3 seconds after
+ * the call waiting begins (this allows for the SAS, CAS, and CWCID spill to be sent first).
+ */
+ analog_p->callwaitdeluxepending = 0;
+ analog_callwaiting_deluxe(analog_p, 0);
+ }
+ ast_mutex_unlock(&p->lock);
+ /* The user shouldn't hear anything after hook flashing, until a decision is made, by the user or when the timer expires. */
+ ast_debug(5, "Dropping frame since Call Waiting Deluxe pending on %s\n", ast_channel_name(ast));
+ return 0;
+ }
+ }
+
if (p->dialing) {
ast_mutex_unlock(&p->lock);
ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",
@@ -12805,6 +12825,7 @@
tmp->usedistinctiveringdetection = usedistinctiveringdetection;
tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
+ tmp->callwaitingdeluxe = conf->chan.callwaitingdeluxe; /* Not used in DAHDI pvt, only analog pvt */
tmp->threewaycalling = conf->chan.threewaycalling;
tmp->adsi = conf->chan.adsi;
tmp->use_smdi = conf->chan.use_smdi;
@@ -13136,6 +13157,7 @@
break;
}
analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
+ analog_p->callwaitingdeluxe = conf->chan.callwaitingdeluxe;
analog_p->ringt = conf->chan.ringt;
analog_p->ringt_base = ringt_base;
analog_p->onhooktime = time(NULL);
@@ -18260,6 +18282,8 @@
confp->chan.callwaiting = ast_true(v->value);
} else if (!strcasecmp(v->name, "callwaitingcallerid")) {
confp->chan.callwaitingcallerid = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "callwaitingdeluxe")) {
+ confp->chan.callwaitingdeluxe = ast_true(v->value);
} else if (!strcasecmp(v->name, "context")) {
ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
} else if (!strcasecmp(v->name, "language")) {
diff --git a/channels/chan_dahdi.h b/channels/chan_dahdi.h
index de813f2..b7e222c 100644
--- a/channels/chan_dahdi.h
+++ b/channels/chan_dahdi.h
@@ -222,6 +222,10 @@
*/
unsigned int callwaitingcallerid:1;
/*!
+ * \brief TRUE if Call Waiting Deluxe options should be available
+ */
+ unsigned int callwaitingdeluxe:1;
+ /*!
* \brief TRUE if support for call forwarding enabled.
* Dial *72 to enable call forwarding.
* Dial *73 to disable call forwarding.
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index b694a96..4893ea5 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -1567,6 +1567,162 @@
}
}
+enum callwaiting_deluxe_option {
+ CWD_CONFERENCE = '3',
+ CWD_HOLD = '6',
+ CWD_DROP = '7',
+ CWD_ANNOUNCEMENT = '8',
+ CWD_FORWARD = '9',
+};
+
+static const char *callwaiting_deluxe_optname(int option)
+{
+ switch (option) {
+ case CWD_CONFERENCE:
+ return "CONFERENCE";
+ case CWD_HOLD:
+ return "HOLD";
+ case CWD_DROP:
+ return "DROP";
+ case CWD_ANNOUNCEMENT:
+ return "ANNOUNCEMENT";
+ case CWD_FORWARD:
+ return "FORWARD";
+ default:
+ return "DEFAULT";
+ }
+}
+
+int analog_callwaiting_deluxe(struct analog_pvt *p, int option)
+{
+ const char *announce_var;
+ char announcement[PATH_MAX];
+
+ ast_debug(1, "Handling Call Waiting on channel %d with option %c: treatment %s\n", p->channel, option, callwaiting_deluxe_optname(option));
+
+ if (!p->subs[ANALOG_SUB_CALLWAIT].owner) {
+ /* This can happen if the caller hook flashes and the call waiting hangs up before the CWD timer expires (1 second) */
+ ast_debug(1, "Call waiting call disappeared before it could be handled?\n");
+ return -1;
+ }
+
+ analog_lock_sub_owner(p, ANALOG_SUB_CALLWAIT);
+ if (!p->subs[ANALOG_SUB_CALLWAIT].owner) {
+ ast_log(LOG_WARNING, "Whoa, the call-waiting call disappeared.\n");
+ return -1;
+ }
+
+ /* Note that when p->callwaitdeluxepending, dahdi_write will drop incoming frames to the channel,
+ * since the user shouldn't hear anything after flashing until either a DTMF has been received
+ * or it's been a second and the decision is made automatically. */
+
+ switch (option) {
+ case CWD_CONFERENCE:
+ /* We should never have a call waiting if we have a 3-way anyways, but check just in case,
+ * there better be no existing SUB_THREEWAY since we're going to make one (and then swap the call wait to it) */
+ if (p->subs[ANALOG_SUB_THREEWAY].owner) {
+ ast_channel_unlock(p->subs[ANALOG_SUB_CALLWAIT].owner);
+ ast_log(LOG_WARNING, "Already have a 3-way call on channel %d, can't conference!\n", p->channel);
+ return -1;
+ }
+
+ /* To conference the incoming call, swap it from SUB_CALLWAIT to SUB_THREEWAY,
+ * and then the existing 3-way logic will ensure that flashing again will drop the call waiting */
+ analog_alloc_sub(p, ANALOG_SUB_THREEWAY);
+ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_CALLWAIT);
+ analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
+
+ ast_verb(3, "Building conference call with %s and %s\n", ast_channel_name(p->subs[ANALOG_SUB_THREEWAY].owner), ast_channel_name(p->subs[ANALOG_SUB_REAL].owner));
+ analog_set_inthreeway(p, ANALOG_SUB_THREEWAY, 1);
+ analog_set_inthreeway(p, ANALOG_SUB_REAL, 1);
+
+ if (ast_channel_state(p->subs[ANALOG_SUB_THREEWAY].owner) == AST_STATE_RINGING) {
+ ast_setstate(p->subs[ANALOG_SUB_THREEWAY].owner, AST_STATE_UP);
+ ast_queue_control(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CONTROL_ANSWER);
+ /* Stop the ringing on the call wait channel (yeah, apparently this is how it's done) */
+ ast_queue_hold(p->subs[ANALOG_SUB_THREEWAY].owner, p->mohsuggest);
+ ast_queue_unhold(p->subs[ANALOG_SUB_THREEWAY].owner);
+ }
+ analog_stop_callwait(p);
+
+ ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner); /* Unlock what was originally SUB_CALLWAIT */
+ break;
+ case CWD_ANNOUNCEMENT:
+ /* We can't just call ast_streamfile here, this thread isn't responsible for media on the call waiting channel.
+ * What we need is something like ast_channel_call_forward_set, that sets a string field that
+ * app_dial will see and do something with. Et voila, ast_channel_dial_announcement_set.
+ * This allows us to tell app_dial to play an audio file, and it will actually handle that.
+ * It's a lot easier than other ways of trying to send early media to the channel
+ * (such as every call from the core to dahdi_read, sending the channel one frame of the audio file, etc.)
+ */
+
+ /* There's not a particularly good stock audio prompt to use here. The Pat Fleet library has some better
+ * ones but we want one that is also in the default Allison Smith library. "One moment please" works okay.
+ * Check if a variable containing the prompt to use was specified on the call waiting channel, and
+ * fall back to a reasonable default if not. */
+
+ /* The SUB_CALLWAIT channel is already locked here, no need to lock and unlock to get the variable. */
+ announce_var = pbx_builtin_getvar_helper(p->subs[ANALOG_SUB_CALLWAIT].owner, "CALLWAITDELUXEANNOUNCEMENT");
+ ast_copy_string(announcement, S_OR(announce_var, "one-moment-please"), sizeof(announcement));
+ ast_debug(2, "Call Waiting Deluxe announcement for %s: %s\n", ast_channel_name(p->subs[ANALOG_SUB_CALLWAIT].owner), announcement);
+ ast_channel_dial_announcement_set(p->subs[ANALOG_SUB_CALLWAIT].owner, announcement);
+ ast_channel_unlock(p->subs[ANALOG_SUB_CALLWAIT].owner);
+ /* Unlike all the other options, the call waiting is still active with this option,
+ * so we don't call analog_stop_callwait(p)
+ * The call waiting will continue to be here, and at some later point the user can flash again and choose a finalizing option
+ * (or even queue the announcement again... and again... and again...)
+ */
+ break;
+ case CWD_FORWARD:
+ /* Go away, call waiting, call again some other day... */
+ analog_stop_callwait(p);
+ /* Can't use p->call_forward exten because that's for *72 forwarding, and sig_analog doesn't
+ * have a Busy/Don't Answer call forwarding exten internally, so let the dialplan deal with it.
+ * by sending the call to the 'f' extension.
+ */
+ ast_channel_call_forward_set(p->subs[ANALOG_SUB_CALLWAIT].owner, "f");
+ ast_channel_unlock(p->subs[ANALOG_SUB_CALLWAIT].owner);
+ /* app_dial already has a verbose message for forwarding, so we don't really need one here also since that does the job */
+ break;
+ case CWD_DROP:
+ /* Fall through: logic is identical to hold, except we drop the original call right after we swap. */
+ case CWD_HOLD:
+ /* Fall through: this option is simply the default */
+ default:
+ /* Swap to call-wait, same as with the non-deluxe call waiting handling. */
+ analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_CALLWAIT);
+ analog_play_tone(p, ANALOG_SUB_REAL, -1);
+ analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
+ ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
+ if (ast_channel_state(p->subs[ANALOG_SUB_REAL].owner) == AST_STATE_RINGING) {
+ ast_setstate(p->subs[ANALOG_SUB_REAL].owner, AST_STATE_UP);
+ ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_ANSWER);
+ }
+ analog_stop_callwait(p);
+
+ if (option == CWD_DROP) {
+ /* Disconnect the previous call (the original call is now the SUB_CALLWAIT since we swapped above) */
+ ast_queue_hangup(p->subs[ANALOG_SUB_CALLWAIT].owner);
+ ast_verb(3, "Dropping original call and swapping to call waiting on %s\n", ast_channel_name(p->subs[ANALOG_SUB_REAL].owner));
+ } else {
+ /* Start music on hold if appropriate */
+ if (!p->subs[ANALOG_SUB_CALLWAIT].inthreeway) {
+ ast_queue_hold(p->subs[ANALOG_SUB_CALLWAIT].owner, p->mohsuggest);
+ }
+ ast_verb(3, "Holding original call and swapping to call waiting on %s\n", ast_channel_name(p->subs[ANALOG_SUB_REAL].owner));
+ }
+
+ /* Stop ringing on the incoming call */
+ ast_queue_hold(p->subs[ANALOG_SUB_REAL].owner, p->mohsuggest);
+ ast_queue_unhold(p->subs[ANALOG_SUB_REAL].owner);
+
+ /* Unlock the call-waiting call that we swapped to real-call. */
+ ast_channel_unlock(p->subs[ANALOG_SUB_REAL].owner);
+ }
+ analog_update_conf(p);
+ return 0;
+}
+
void analog_handle_dtmf(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub idx, struct ast_frame **dest)
{
struct ast_frame *f = *dest;
@@ -1604,6 +1760,50 @@
p->subs[idx].f.frametype = AST_FRAME_NULL;
p->subs[idx].f.subclass.integer = 0;
*dest = &p->subs[idx].f;
+ } else if (p->callwaitdeluxepending) {
+ if (f->frametype == AST_FRAME_DTMF_END) {
+ unsigned int mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
+ p->callwaitdeluxepending = 0;
+
+ /* This is the case where a user explicitly took action (made a decision)
+ * for Call Waiting Deluxe.
+ * Because we already handled the hook flash, if the user doesn't do
+ * anything within a second, then we still need to eventually take
+ * the default action (swap) for the call waiting.
+ *
+ * dahdi_write will also drop audio if callwaitdeluxepending is set HIGH,
+ * and also check if flashtime hits 1000, in which case it will set the flag LOW and then take the
+ * default action, e.g. analog_callwaiting_deluxe(p, 0);
+ */
+
+ /* Slightly less than 1000, so there's no chance of a race condition
+ * between do_monitor when it sees flashtime hitting 1000 and us. */
+ if (mssinceflash > 990) {
+ /* This was more than a second ago, clear the flag and process normally. */
+ /* Because another thread has to monitor channels with pending CWDs,
+ * in theory, we shouldn't need to check this here. */
+ ast_debug(1, "It's been %u ms since the last flash, this is not a Call Waiting Deluxe DTMF\n", mssinceflash);
+ analog_cb_handle_dtmf(p, ast, idx, dest);
+ return;
+ }
+ /* Okay, actually do something now. */
+ switch (f->subclass.integer) {
+ case CWD_CONFERENCE:
+ case CWD_HOLD:
+ case CWD_DROP:
+ case CWD_ANNOUNCEMENT:
+ case CWD_FORWARD:
+ ast_debug(1, "Got some DTMF, but it's for Call Waiting Deluxe: %c\n", f->subclass.integer);
+ analog_callwaiting_deluxe(p, f->subclass.integer);
+ break;
+ default:
+ ast_log(LOG_WARNING, "Invalid Call Waiting Deluxe option (%c), using default\n", f->subclass.integer);
+ analog_callwaiting_deluxe(p, 0);
+ }
+ }
+ p->subs[idx].f.frametype = AST_FRAME_NULL;
+ p->subs[idx].f.subclass.integer = 0;
+ *dest = &p->subs[idx].f;
} else {
analog_cb_handle_dtmf(p, ast, idx, dest);
}
@@ -2892,6 +3092,7 @@
analog_get_and_handle_alarms(p);
cause_code->ast_cause = AST_CAUSE_NETWORK_OUT_OF_ORDER;
case ANALOG_EVENT_ONHOOK:
+ p->callwaitdeluxepending = 0;
ast_queue_control_data(ast, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
ast_channel_hangupcause_hash_set(ast, cause_code, data_size);
switch (p->sig) {
@@ -3207,6 +3408,7 @@
}
/* Remember last time we got a flash-hook */
gettimeofday(&p->flashtime, NULL);
+ p->callwaitdeluxepending = 0;
switch (mysig) {
case ANALOG_SIG_FXOLS:
case ANALOG_SIG_FXOGS:
@@ -3235,6 +3437,20 @@
goto winkflashdone;
}
+ /* If line has Call Waiting Deluxe, see what the user wants to do.
+ * Only do this if this is an as yet unanswered call waiting, not an existing, answered SUB_CALLWAIT. */
+ if (ast_channel_state(p->subs[ANALOG_SUB_CALLWAIT].owner) == AST_STATE_RINGING) {
+ if (p->callwaitingdeluxe) {
+ /* This thread cannot block, so just set the flag that we need
+ * to wait for a Call Waiting Deluxe option (or let it time out),
+ * and then we're done for now. */
+ ast_channel_unlock(p->subs[ANALOG_SUB_CALLWAIT].owner);
+ p->callwaitdeluxepending = 1;
+ ast_debug(1, "Deferring call waiting manipulation, waiting for Call Waiting Deluxe option from user\n");
+ goto winkflashdone;
+ }
+ }
+
/* Swap to call-wait */
analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_CALLWAIT);
analog_play_tone(p, ANALOG_SUB_REAL, -1);
@@ -3768,6 +3984,7 @@
case ANALOG_SIG_FXOKS:
res = analog_off_hook(i);
i->fxsoffhookstate = 1;
+ i->callwaitdeluxepending = 0;
if (res && (errno == EBUSY)) {
break;
}
diff --git a/channels/sig_analog.h b/channels/sig_analog.h
index 7e9acda..6dfd9df 100644
--- a/channels/sig_analog.h
+++ b/channels/sig_analog.h
@@ -320,6 +320,7 @@
/* XXX: All variables after this are internal */
unsigned int callwaiting:1; /*!< TRUE if call waiting is enabled. (Active option) */
+ unsigned int callwaitingdeluxe:1; /*!< TRUE if Call Waiting Deluxe options are available */
unsigned int dialednone:1;
unsigned int dialing:1; /*!< TRUE if in the process of dialing digits or sending something */
unsigned int dnd:1; /*!< TRUE if Do-Not-Disturb is enabled. */
@@ -335,6 +336,11 @@
*/
unsigned int callwaitcas:1;
+ /*!
+ * \brief TRUE if a Call Waiting Deluxe action is currently pending.
+ */
+ unsigned int callwaitdeluxepending:1;
+
char callwait_num[AST_MAX_EXTENSION];
char callwait_name[AST_MAX_EXTENSION];
char lastcid_num[AST_MAX_EXTENSION];
@@ -382,6 +388,8 @@
int analog_config_complete(struct analog_pvt *p);
+int analog_callwaiting_deluxe(struct analog_pvt *p, int option);
+
void analog_handle_dtmf(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub index, struct ast_frame **dest);
enum analog_cid_start analog_str_to_cidstart(const char *value);
diff --git a/configs/samples/chan_dahdi.conf.sample b/configs/samples/chan_dahdi.conf.sample
index 6b29549..4ddc901 100644
--- a/configs/samples/chan_dahdi.conf.sample
+++ b/configs/samples/chan_dahdi.conf.sample
@@ -676,6 +676,30 @@
;
callwaiting=yes
;
+; Whether or not to allow for Call Waiting Deluxe options to be used.
+; The Call Waiting Deluxe options are:
+; 3: Conference - conference the call waiting call with the existing call
+; 6: Hold (default) - hold the current call and switch to the new one
+; 7: Drop - drop current call and switch to new (same as hanging up and answering)
+; 8: Announcement - play announcement to call waiting caller telling them to hold
+; 9: Forward - forward the call waiting call to a preconfigured extension
+;
+; Some CPE (Caller ID units, screenphones, etc.) have dedicated buttons for utilizing
+; the Call Waiting Deluxe features, but these can also be used from any phone manually
+; by simply hook flashing as usual and then quickly dialing the appropriate DTMF digit.
+; If not digit is received within 1 second, the default action is assumed,
+; as if Call Waiting Deluxe was not used.
+;
+; The following extensions are also available in the dialplan to utilize this functionality:
+; - The CALLWAITDELUXEANNOUNCEMENT variable can be set on the incoming channel to control the
+; announcement prompt played to the call waiting caller. Default is "one-moment-please".
+; - If the forward option is used, the call waiting channel will be forwarded to the 'f' extension
+; in the channel's configured context. You can then use any dialplan mechanism to route the call.
+;
+; Default is 'no'.
+;
+;callwaitingdeluxe=yes
+;
; Configure the number of outstanding call waiting calls for internal ISDN
; endpoints before bouncing the calls as busy. This option is equivalent to
; the callwaiting option for analog ports.
diff --git a/doc/CHANGES-staging/callwaitingdeluxe.txt b/doc/CHANGES-staging/callwaitingdeluxe.txt
new file mode 100644
index 0000000..dd81a94
--- /dev/null
+++ b/doc/CHANGES-staging/callwaitingdeluxe.txt
@@ -0,0 +1,5 @@
+Subject: sig_analog
+
+Call Waiting Deluxe options are now supported
+for FXS channels. Refer to the sample config
+for more information about these options.
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index e5613df..c1c8e20 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -4140,6 +4140,7 @@
DECLARE_STRINGFIELD_SETTERS_FOR(parkinglot);
DECLARE_STRINGFIELD_SETTERS_FOR(hangupsource);
DECLARE_STRINGFIELD_SETTERS_FOR(dialcontext);
+DECLARE_STRINGFIELD_SETTERS_FOR(dial_announcement);
const char *ast_channel_name(const struct ast_channel *chan);
const char *ast_channel_language(const struct ast_channel *chan);
@@ -4154,6 +4155,7 @@
const char *ast_channel_parkinglot(const struct ast_channel *chan);
const char *ast_channel_hangupsource(const struct ast_channel *chan);
const char *ast_channel_dialcontext(const struct ast_channel *chan);
+const char *ast_channel_dial_announcement(const struct ast_channel *chan);
const char *ast_channel_appl(const struct ast_channel *chan);
void ast_channel_appl_set(struct ast_channel *chan, const char *value);
diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c
index bc0fb4c..d52c84a 100644
--- a/main/channel_internal_api.c
+++ b/main/channel_internal_api.c
@@ -110,6 +110,7 @@
AST_STRING_FIELD(parkinglot); /*! Default parking lot, if empty, default parking lot */
AST_STRING_FIELD(hangupsource); /*! Who is responsible for hanging up this channel */
AST_STRING_FIELD(dialcontext); /*!< Dial: Extension context that we were called from */
+ AST_STRING_FIELD(dial_announcement); /*!< Audio file to play if asked to dial on this interface */
);
struct ast_channel_id uniqueid; /*!< Unique Channel Identifier - can be specified on creation */
@@ -286,6 +287,7 @@
DEFINE_STRINGFIELD_SETTERS_FOR(parkinglot, 0);
DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(hangupsource, 0, 0, AST_CHANNEL_SNAPSHOT_INVALIDATE_HANGUP);
DEFINE_STRINGFIELD_SETTERS_FOR(dialcontext, 0);
+DEFINE_STRINGFIELD_SETTERS_FOR(dial_announcement, 0);
#define DEFINE_STRINGFIELD_GETTER_FOR(field) const char *ast_channel_##field(const struct ast_channel *chan) \
{ \
@@ -303,6 +305,7 @@
DEFINE_STRINGFIELD_GETTER_FOR(parkinglot);
DEFINE_STRINGFIELD_GETTER_FOR(hangupsource);
DEFINE_STRINGFIELD_GETTER_FOR(dialcontext);
+DEFINE_STRINGFIELD_GETTER_FOR(dial_announcement);
const char *ast_channel_uniqueid(const struct ast_channel *chan)
{
--
To view, visit https://gerrit.asterisk.org/c/asterisk/+/19748
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: Ifd222b5f757c8dd382158a89c6b6ad9a82b07421
Gerrit-Change-Number: 19748
Gerrit-PatchSet: 1
Gerrit-Owner: N A <asterisk at phreaknet.org>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20221222/d206194f/attachment-0001.html>
More information about the asterisk-code-review
mailing list