Merge 4356f16234
into 953dc3d127
This commit is contained in:
commit
52185a194b
|
@ -1720,6 +1720,15 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
|
|||
case AST_CONTROL_PVT_CAUSE_CODE:
|
||||
ast_indicate_data(in, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen);
|
||||
break;
|
||||
case AST_CONTROL_PLAYBACK_BEGIN:
|
||||
if (!f->data.ptr) {
|
||||
ast_log(LOG_WARNING, "Got playback begin directive without filename on %s\n", ast_channel_name(c));
|
||||
} else {
|
||||
const char *filename = f->data.ptr;
|
||||
ast_verb(3, "Playing audio file %s on %s\n", filename, ast_channel_name(in));
|
||||
ast_streamfile(in, filename, ast_channel_language(in));
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
if (single && !caller_entertained) {
|
||||
ast_verb(3, "%s stopped sounds\n", ast_channel_name(c));
|
||||
|
|
|
@ -9277,6 +9277,26 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
|
|||
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",
|
||||
|
@ -13033,6 +13053,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
|
|||
|
||||
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->threewaysilenthold = conf->chan.threewaysilenthold;
|
||||
tmp->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Not used in chan_dahdi.c, just analog pvt, but must exist on the DAHDI pvt anyways */
|
||||
|
@ -13371,6 +13392,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
|
|||
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);
|
||||
|
@ -18569,6 +18591,8 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
|
|||
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")) {
|
||||
|
|
|
@ -229,6 +229,10 @@ struct dahdi_pvt {
|
|||
* \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
|
||||
*/
|
||||
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.
|
||||
|
|
|
@ -1490,6 +1490,7 @@ static int iax2_is_control_frame_allowed(int subtype)
|
|||
case AST_CONTROL_STREAM_RESTART:
|
||||
case AST_CONTROL_STREAM_REVERSE:
|
||||
case AST_CONTROL_STREAM_FORWARD:
|
||||
case AST_CONTROL_PLAYBACK_BEGIN: /* Only supported by app_dial currently */
|
||||
/* None of these playback stream control frames should go across the link. */
|
||||
case AST_CONTROL_RECORD_CANCEL:
|
||||
case AST_CONTROL_RECORD_STOP:
|
||||
|
|
|
@ -1590,6 +1590,161 @@ static int analog_handles_digit(struct ast_frame *f)
|
|||
}
|
||||
}
|
||||
|
||||
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_ERROR, "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_HOLD: /* The CI-7112 Visual Director sends "HOLD" for "Play hold message" rather than "ANNOUNCEMENT". For default behavior, nothing is actually sent. */
|
||||
case CWD_ANNOUNCEMENT:
|
||||
/* We can't just call ast_streamfile here, this thread isn't responsible for media on the call waiting channel.
|
||||
* Indicate to the dialing channel in app_dial that it needs to play media.
|
||||
*
|
||||
* This is 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_unlock(p->subs[ANALOG_SUB_CALLWAIT].owner);
|
||||
/* Tell app_dial what file to play. */
|
||||
ast_queue_control_data(p->subs[ANALOG_SUB_CALLWAIT].owner, AST_CONTROL_PLAYBACK_BEGIN, announcement, strlen(announcement) + 1);
|
||||
/* 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. */
|
||||
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;
|
||||
|
@ -1627,6 +1782,50 @@ void analog_handle_dtmf(struct analog_pvt *p, struct ast_channel *ast, enum anal
|
|||
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);
|
||||
}
|
||||
|
@ -2965,6 +3164,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
|
|||
break;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
|
@ -3280,6 +3480,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
|
|||
}
|
||||
/* 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:
|
||||
|
@ -3308,6 +3509,20 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
|
|||
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);
|
||||
|
@ -3842,6 +4057,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
|
|||
res = analog_off_hook(i);
|
||||
i->fxsoffhookstate = 1;
|
||||
i->cshactive = 0;
|
||||
i->callwaitdeluxepending = 0;
|
||||
if (res && (errno == EBUSY)) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -331,6 +331,7 @@ struct analog_pvt {
|
|||
|
||||
/* 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 cshactive:1; /*!< TRUE if FXS channel is currently held by an incoming call */
|
||||
unsigned int dialednone:1;
|
||||
unsigned int dialing:1; /*!< TRUE if in the process of dialing digits or sending something */
|
||||
|
@ -346,6 +347,12 @@ struct analog_pvt {
|
|||
* gives a positive reply.
|
||||
*/
|
||||
unsigned int callwaitcas:1;
|
||||
|
||||
/*!
|
||||
* \brief TRUE if a Call Waiting Deluxe action is currently pending.
|
||||
*/
|
||||
unsigned int callwaitdeluxepending:1;
|
||||
|
||||
unsigned int call_qualifier:1; /*!< Call qualifier delivery */
|
||||
|
||||
char callwait_num[AST_MAX_EXTENSION];
|
||||
|
@ -397,6 +404,8 @@ void *analog_handle_init_event(struct analog_pvt *i, int event);
|
|||
|
||||
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);
|
||||
|
|
|
@ -685,6 +685,31 @@ usecallerid=yes
|
|||
;
|
||||
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
|
||||
; 7: Drop - drop current call and switch to new (same as hanging up and answering)
|
||||
; 6/8: Announcement - play announcement to call waiting caller telling them to hold
|
||||
; 9: Forward - forward the call waiting call to a preconfigured extension
|
||||
; Doing nothing after 1 second triggers default behavior of holding the current call
|
||||
; and switching to the new one.
|
||||
;
|
||||
; 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 no 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.
|
||||
|
|
|
@ -380,6 +380,9 @@ static void print_frame(struct ast_frame *frame)
|
|||
case AST_CONTROL_RECORD_MUTE:
|
||||
ast_verbose("SubClass: RECORD_MUTE\n");
|
||||
break;
|
||||
case AST_CONTROL_PLAYBACK_BEGIN:
|
||||
ast_verbose("SubClass: PLAYBACK_BEGIN\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (frame->subclass.integer == -1) {
|
||||
|
|
|
@ -335,6 +335,7 @@ enum ast_control_frame_type {
|
|||
AST_CONTROL_STREAM_RESTART = 1002, /*!< Indicate to a channel in playback to restart the stream */
|
||||
AST_CONTROL_STREAM_REVERSE = 1003, /*!< Indicate to a channel in playback to rewind */
|
||||
AST_CONTROL_STREAM_FORWARD = 1004, /*!< Indicate to a channel in playback to fast forward */
|
||||
AST_CONTROL_PLAYBACK_BEGIN = 1005, /*!< Indicate to a dialing interface that playback of an audio file should begin on the dialing channel. Currently only supported by app_dial. */
|
||||
/* Control frames to manipulate recording on a channel. */
|
||||
AST_CONTROL_RECORD_CANCEL = 1100, /*!< Indicated to a channel in record to stop recording and discard the file */
|
||||
AST_CONTROL_RECORD_STOP = 1101, /*!< Indicated to a channel in record to stop recording */
|
||||
|
|
|
@ -4323,6 +4323,7 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con
|
|||
case AST_CONTROL_RECORD_STOP:
|
||||
case AST_CONTROL_RECORD_SUSPEND:
|
||||
case AST_CONTROL_RECORD_MUTE:
|
||||
case AST_CONTROL_PLAYBACK_BEGIN:
|
||||
break;
|
||||
|
||||
case AST_CONTROL_INCOMPLETE:
|
||||
|
@ -4624,6 +4625,7 @@ static int indicate_data_internal(struct ast_channel *chan, int _condition, cons
|
|||
case AST_CONTROL_RECORD_STOP:
|
||||
case AST_CONTROL_RECORD_SUSPEND:
|
||||
case AST_CONTROL_RECORD_MUTE:
|
||||
case AST_CONTROL_PLAYBACK_BEGIN:
|
||||
/* Nothing left to do for these. */
|
||||
res = 0;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue