Index: channel.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channel.c,v
retrieving revision 1.168
diff -u -r1.168 channel.c
--- channel.c	15 Jan 2005 23:48:11 -0000	1.168
+++ channel.c	17 Jan 2005 11:53:43 -0000
@@ -2812,6 +2812,10 @@
 		}
 
 		if ((f->frametype == AST_FRAME_CONTROL) && !(config->flags & AST_BRIDGE_IGNORE_SIGS)) {
+			if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD)) {
+				ast_indicate(who == c0 ? c1 : c0, f->subclass);
+				goto takeout;
+			}
 			*fo = f;
 			*rc = who;
 			res =  0;
@@ -2861,9 +2865,10 @@
 				else 
 					ast_write(c0, f);
 			}
-			ast_frfree(f);
-		} else
-			ast_frfree(f);
+		}
+takeout:
+		ast_frfree(f);
+
 		/* Swap who gets priority */
 		cs[2] = cs[0];
 		cs[0] = cs[1];
Index: apps/app_dial.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_dial.c,v
retrieving revision 1.126
diff -u -r1.126 app_dial.c
--- apps/app_dial.c	16 Jan 2005 07:58:51 -0000	1.126
+++ apps/app_dial.c	17 Jan 2005 11:53:43 -0000
@@ -393,6 +393,16 @@
 							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: channels/chan_zap.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_zap.c,v
retrieving revision 1.399
diff -u -r1.399 chan_zap.c
--- channels/chan_zap.c	15 Jan 2005 21:51:37 -0000	1.399
+++ channels/chan_zap.c	17 Jan 2005 11:53:45 -0000
@@ -4406,6 +4406,16 @@
 #endif
 				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
 			break;
+#ifdef AST_CONTROL_HOLD
+		case AST_CONTROL_HOLD:
+			res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
+			break;
+#endif
+#ifdef AST_CONTROL_UNHOLD
+		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 +8188,28 @@
 					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
 				}
 				break;
+#ifdef PRI_EVENT_NOTIFY
+			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 {
+					ast_mutex_lock(&pri->pvts[chanpos]->lock);
+					switch(e->notify.info) {
+					case PRI_NOTIFY_REMOTE_HOLD:
+						if (ast_bridged_channel(pri->pvts[chanpos]->owner))
+							ast_indicate(ast_bridged_channel(pri->pvts[chanpos]->owner), AST_CONTROL_HOLD);
+						break;
+					case PRI_NOTIFY_REMOTE_RETRIEVAL:
+						if (ast_bridged_channel(pri->pvts[chanpos]->owner))
+							ast_indicate(ast_bridged_channel(pri->pvts[chanpos]->owner), AST_CONTROL_UNHOLD);
+						break;
+					}
+					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+				}
+				break;
+#endif
 			default:
 				ast_log(LOG_DEBUG, "Event: %d\n", e->e);
 			}
Index: include/asterisk/frame.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/frame.h,v
retrieving revision 1.40
diff -u -r1.40 frame.h
--- include/asterisk/frame.h	15 Jan 2005 23:48:12 -0000	1.40
+++ include/asterisk/frame.h	17 Jan 2005 11:53:45 -0000
@@ -226,6 +226,10 @@
 #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: res/res_features.c
===================================================================
RCS file: /usr/cvsroot/asterisk/res/res_features.c,v
retrieving revision 1.34
diff -u -r1.34 res_features.c
--- res/res_features.c	11 Jan 2005 18:24:27 -0000	1.34
+++ res/res_features.c	17 Jan 2005 11:53:45 -0000
@@ -229,8 +229,10 @@
 
 			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 @@
 	}
 	/* 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 @@
 	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 @@
 	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 @@
 		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 @@
 	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 @@
 	}
 	/* 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 @@
 	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 @@
 					}
 					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 @@
 				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 @@
 			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 @@
 	}
 	ast_moh_stop(transferee);
 	ast_autoservice_stop(transferee);
-
+	ast_indicate(transferee, AST_CONTROL_UNHOLD);
 
 	return FEATURE_RETURN_SUCCESS;
 }
@@ -1098,6 +1115,7 @@
 			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 @@
 		}
  
 		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);
