summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xapps/app_dial.c10
-rwxr-xr-xchannel.c24
-rwxr-xr-xchannels/chan_zap.c29
-rwxr-xr-xinclude/asterisk/frame.h4
-rwxr-xr-xres/res_features.c25
5 files changed, 81 insertions, 11 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c
index 2828262b7..16323881c 100755
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -393,6 +393,16 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
if (!ast_test_flag(outgoing, DIAL_RINGBACKONLY))
ast_indicate(in, AST_CONTROL_PROGRESS);
break;
+ case AST_CONTROL_HOLD:
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", o->chan->name);
+ ast_indicate(in, AST_CONTROL_HOLD);
+ break;
+ case AST_CONTROL_UNHOLD:
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", o->chan->name);
+ ast_indicate(in, AST_CONTROL_UNHOLD);
+ break;
case AST_CONTROL_OFFHOOK:
case AST_CONTROL_FLASH:
/* Ignore going off hook and flash */
diff --git a/channel.c b/channel.c
index 10e668300..68734d031 100755
--- a/channel.c
+++ b/channel.c
@@ -1478,6 +1478,10 @@ int ast_indicate(struct ast_channel *chan, int condition)
/* ast_playtones_stop(chan); */
} else if (condition == AST_CONTROL_PROCEEDING) {
/* Do nothing, really */
+ } else if (condition == AST_CONTROL_HOLD) {
+ /* Do nothing.... */
+ } else if (condition == AST_CONTROL_UNHOLD) {
+ /* Do nothing.... */
} else {
/* not handled */
ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
@@ -2812,11 +2816,15 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct as
}
if ((f->frametype == AST_FRAME_CONTROL) && !(config->flags & AST_BRIDGE_IGNORE_SIGS)) {
- *fo = f;
- *rc = who;
- res = 0;
- ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
- break;
+ if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD)) {
+ ast_indicate(who == c0 ? c1 : c0, f->subclass);
+ } else {
+ *fo = f;
+ *rc = who;
+ res = 0;
+ ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
+ break;
+ }
}
if ((f->frametype == AST_FRAME_VOICE) ||
(f->frametype == AST_FRAME_TEXT) ||
@@ -2861,9 +2869,9 @@ tackygoto:
else
ast_write(c0, f);
}
- ast_frfree(f);
- } else
- ast_frfree(f);
+ }
+ ast_frfree(f);
+
/* Swap who gets priority */
cs[2] = cs[0];
cs[0] = cs[1];
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index 292dfc191..36efc2176 100755
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -4406,6 +4406,14 @@ static int zt_indicate(struct ast_channel *chan, int condition)
#endif
res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
break;
+#ifdef ZAPATA_PRI
+ case AST_CONTROL_HOLD:
+ res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
+ break;
+ case AST_CONTROL_UNHOLD:
+ res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
+ break;
+#endif
case AST_CONTROL_RADIO_KEY:
if (p->radio)
res = zt_set_hook(p->subs[index].zfd, ZT_OFFHOOK);
@@ -8178,6 +8186,27 @@ static void *pri_dchannel(void *vpri)
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
break;
+ case PRI_EVENT_NOTIFY:
+ chanpos = pri_find_principle(pri, e->notify.channel);
+ if (chanpos < 0) {
+ ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
+ PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
+ } else {
+ struct ast_frame f = { AST_FRAME_CONTROL, };
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ switch(e->notify.info) {
+ case PRI_NOTIFY_REMOTE_HOLD:
+ f.subclass = AST_CONTROL_HOLD;
+ zap_queue_frame(pri->pvts[chanpos], &f, pri);
+ break;
+ case PRI_NOTIFY_REMOTE_RETRIEVAL:
+ f.subclass = AST_CONTROL_UNHOLD;
+ zap_queue_frame(pri->pvts[chanpos], &f, pri);
+ break;
+ }
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+ }
+ break;
default:
ast_log(LOG_DEBUG, "Event: %d\n", e->e);
}
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index 035105781..c634254f6 100755
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -226,6 +226,10 @@ struct ast_frame_chain {
#define AST_CONTROL_PROGRESS 14
/*! Indicate CALL PROCEEDING */
#define AST_CONTROL_PROCEEDING 15
+/*! Indicate call is placed on hold */
+#define AST_CONTROL_HOLD 16
+/*! Indicate call is left from hold */
+#define AST_CONTROL_UNHOLD 17
#define AST_SMOOTHER_FLAG_G729 (1 << 0)
diff --git a/res/res_features.c b/res/res_features.c
index e06222914..691969781 100755
--- a/res/res_features.c
+++ b/res/res_features.c
@@ -229,8 +229,10 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
pu->chan = chan;
/* Start music on hold */
- if (chan != peer)
+ if (chan != peer) {
+ ast_indicate(pu->chan, AST_CONTROL_HOLD);
ast_moh_start(pu->chan, NULL);
+ }
gettimeofday(&pu->start, NULL);
pu->parkingnum = x;
if (timeout > 0)
@@ -478,6 +480,7 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
}
/* Start autoservice on chan while we talk
to the originator */
+ ast_indicate(transferee, AST_CONTROL_HOLD);
ast_autoservice_start(transferee);
ast_moh_start(transferee, NULL);
@@ -488,11 +491,13 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
if ((res=ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
ast_moh_stop(transferee);
ast_autoservice_stop(transferee);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
return res;
}
if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
ast_moh_stop(transferee);
ast_autoservice_stop(transferee);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
return res;
}
ast_stopstream(transferer);
@@ -507,12 +512,15 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
if (res < 0) {
ast_moh_stop(transferee);
ast_autoservice_stop(transferee);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
return res;
}
if (!strcmp(newext, ast_parking_ext())) {
ast_moh_stop(transferee);
- if (ast_autoservice_stop(transferee))
+ res = ast_autoservice_stop(transferee);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
+ if (res)
res = -1;
else if (!ast_park_call(transferee, transferer, 0, NULL)) {
/* We return non-zero, but tell the PBX not to hang the channel when
@@ -533,6 +541,7 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
ast_moh_stop(transferee);
res=ast_autoservice_stop(transferee);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
if (!transferee->pbx) {
/* Doh! Use our handy async_goto functions */
if (option_verbose > 2)
@@ -559,12 +568,14 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
if (res) {
ast_moh_stop(transferee);
ast_autoservice_stop(transferee);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
return res;
}
res = ast_waitstream(transferer, AST_DIGIT_ANY);
ast_stopstream(transferer);
ast_moh_stop(transferee);
res = ast_autoservice_stop(transferee);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
if (res) {
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
@@ -606,6 +617,7 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
}
/* Start autoservice on chan while we talk
to the originator */
+ ast_indicate(transferee, AST_CONTROL_HOLD);
ast_autoservice_start(transferee);
ast_moh_start(transferee, NULL);
@@ -613,11 +625,13 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
if ((res=ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
ast_moh_stop(transferee);
ast_autoservice_stop(transferee);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
return res;
}
if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
ast_moh_stop(transferee);
ast_autoservice_stop(transferee);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
return res;
}
if ((ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout))) {
@@ -649,6 +663,7 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
}
ast_moh_stop(transferee);
ast_autoservice_stop(transferee);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
transferer->_softhangup = 0;
return FEATURE_RETURN_SUCCESS;
}
@@ -722,6 +737,7 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
ast_log(LOG_WARNING, "Unable to create channel Local/%s do you have chan_local?\n",dialstr);
ast_moh_stop(transferee);
ast_autoservice_stop(transferee);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
if (!ast_strlen_zero(xferfailsound)) {
res = ast_streamfile(transferer, xferfailsound, transferer->language);
if (!res && (ast_waitstream(transferer, "") < 0)) {
@@ -734,6 +750,7 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
ast_moh_stop(transferee);
ast_autoservice_stop(transferee);
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
res = ast_streamfile(transferer, "beeperr", transferer->language);
if (!res && (ast_waitstream(transferer, "") < 0)) {
return -1;
@@ -748,7 +765,7 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
}
ast_moh_stop(transferee);
ast_autoservice_stop(transferee);
-
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
return FEATURE_RETURN_SUCCESS;
}
@@ -1098,6 +1115,7 @@ static void *do_parking_thread(void *ignore)
if (tms > pu->parkingtime) {
/* Stop music on hold */
ast_moh_stop(pu->chan);
+ ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
/* Get chan, exten from derived kludge */
if (pu->peername[0]) {
peername = ast_strdupa(pu->peername);
@@ -1299,6 +1317,7 @@ static int park_exec(struct ast_channel *chan, void *data)
}
ast_moh_stop(peer);
+ ast_indicate(peer, AST_CONTROL_UNHOLD);
res = ast_channel_make_compatible(chan, peer);
if (res < 0) {
ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);