Merge hold patch (bug #1840)
authorMark Spencer <markster@digium.com>
Mon, 17 Jan 2005 12:37:55 +0000 (12:37 +0000)
committerMark Spencer <markster@digium.com>
Mon, 17 Jan 2005 12:37:55 +0000 (12:37 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4823 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_dial.c
channel.c
channels/chan_zap.c
include/asterisk/frame.h
res/res_features.c

index 2828262..1632388 100755 (executable)
@@ -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 */
index 10e6683..68734d0 100755 (executable)
--- 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];
index 292dfc1..36efc21 100755 (executable)
@@ -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);
                        }
index 0351057..c634254 100755 (executable)
@@ -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)
 
index e062229..6919697 100755 (executable)
@@ -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);