Index: channel.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channel.c,v
retrieving revision 1.148
diff -u -r1.148 channel.c
--- channel.c	7 Nov 2004 16:21:00 -0000	1.148
+++ channel.c	15 Nov 2004 05:10:58 -0000
@@ -2706,6 +2706,11 @@
 		}
 
 		if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
+			if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD)) {
+				ast_indicate(who == c0 ? c1 : c0, f->subclass);
+				ast_frfree(f);
+				goto takeout;
+			}
 			*fo = f;
 			*rc = who;
 			res =  0;
@@ -2758,6 +2763,7 @@
 			ast_frfree(f);
 		} else
 			ast_frfree(f);
+takeout:
 		/* 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.104
diff -u -r1.104 app_dial.c
--- apps/app_dial.c	7 Nov 2004 21:49:43 -0000	1.104
+++ apps/app_dial.c	15 Nov 2004 05:10:58 -0000
@@ -363,6 +363,16 @@
 							if (!outgoing->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.377
diff -u -r1.377 chan_zap.c
--- channels/chan_zap.c	13 Nov 2004 23:56:50 -0000	1.377
+++ channels/chan_zap.c	15 Nov 2004 05:10:59 -0000
@@ -4358,6 +4358,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);
@@ -8097,6 +8107,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.35
diff -u -r1.35 frame.h
--- include/asterisk/frame.h	26 Aug 2004 04:56:26 -0000	1.35
+++ include/asterisk/frame.h	15 Nov 2004 05:10:59 -0000
@@ -217,6 +217,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.21
diff -u -r1.21 res_features.c
--- res/res_features.c	3 Nov 2004 22:37:55 -0000	1.21
+++ res/res_features.c	15 Nov 2004 05:10:59 -0000
@@ -169,8 +169,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)
@@ -433,6 +435,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);
 
@@ -443,11 +446,13 @@
 				if ((res=ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
 					ast_moh_stop(transferee);
 					ast_autoservice_stop(transferee);
+					ast_indicate(transferee, AST_CONTROL_UNHOLD);
 					break;
 				}
 				if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
 					ast_moh_stop(transferee);
 					ast_autoservice_stop(transferee);
+					ast_indicate(transferee, AST_CONTROL_UNHOLD);
 					break;
 				}
 				ast_stopstream(transferer);
@@ -474,6 +479,7 @@
 				if (res < 0) {
 					ast_moh_stop(transferee);
 					ast_autoservice_stop(transferee);
+					ast_indicate(transferee, AST_CONTROL_UNHOLD);
 					break;
 				}
 				if (!strcmp(newext, ast_parking_ext())) {
@@ -500,6 +506,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 funcitons */
 						if (option_verbose > 2) 
@@ -524,12 +531,14 @@
 				if (res) {
 					ast_moh_stop(transferee);
 					ast_autoservice_stop(transferee);
+					ast_indicate(transferee, AST_CONTROL_UNHOLD);
 					break;
 				}
 				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);
@@ -596,6 +605,7 @@
 					ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->chan->context, pu->chan->exten, pu->chan->priority);
 				/* Stop music on hold */
 				ast_moh_stop(pu->chan);
+				ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
 				/* Start up the PBX, or hang them up */
 				if (ast_pbx_start(pu->chan))  {
 					ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
@@ -766,6 +776,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);
