[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