From 496adc6fc08da92e9c151829ed1db9e9fc480ce4 Mon Sep 17 00:00:00 2001
From: Joshua Colp <jcolp@digium.com>
Date: Wed, 5 Mar 2008 22:43:22 +0000
Subject: [PATCH] Merged revisions 106235 via svnmerge from
 https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r106235 | file | 2008-03-05 18:32:10 -0400 (Wed, 05 Mar 2008) | 4 lines

Add a control frame to indicate the source of media has changed. Depending on the underlying technology it may need to change some things.
(closes issue #12148)
Reported by: jcomellas

........


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@106239 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 apps/app_dial.c          |  7 ++++++-
 apps/app_followme.c      |  3 +++
 channels/chan_alsa.c     |  1 +
 channels/chan_console.c  |  1 +
 channels/chan_h323.c     |  4 ++++
 channels/chan_mgcp.c     |  3 +++
 channels/chan_oss.c      |  1 +
 channels/chan_phone.c    | 27 +++++++++++++++------------
 channels/chan_sip.c      |  3 +++
 channels/chan_skinny.c   |  3 +++
 channels/chan_unistim.c  |  1 +
 channels/chan_zap.c      |  3 +++
 include/asterisk/frame.h |  4 +++-
 main/channel.c           | 12 ++++++++++++
 main/dial.c              |  4 ++++
 main/file.c              |  1 +
 main/rtp.c               |  6 ++++--
 17 files changed, 68 insertions(+), 16 deletions(-)

diff --git a/apps/app_dial.c b/apps/app_dial.c
index 5698c1945c..b52a97b2de 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -717,6 +717,10 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
 					ast_verb(3, "%s requested a video update, passing it to %s\n", c->name, in->name);
 					ast_indicate(in, AST_CONTROL_VIDUPDATE);
 					break;
+				case AST_CONTROL_SRCUPDATE:
+					ast_verb(3, "%s requested a source update, passing it to %s\n", c->name, in->name);
+					ast_indicate(in, AST_CONTROL_SRCUPDATE);
+					break;
 				case AST_CONTROL_PROCEEDING:
 					ast_verb(3, "%s is proceeding passing it to %s\n", c->name, in->name);
 					if (single && CAN_EARLY_BRIDGE(peerflags))
@@ -820,7 +824,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
 			if (single && (f->frametype == AST_FRAME_CONTROL) &&
 				((f->subclass == AST_CONTROL_HOLD) ||
 				(f->subclass == AST_CONTROL_UNHOLD) ||
-				(f->subclass == AST_CONTROL_VIDUPDATE))) {
+				(f->subclass == AST_CONTROL_VIDUPDATE) ||
+				 (f->subclass == AST_CONTROL_SRCUPDATE))) {
 				ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
 				ast_indicate_data(outgoing->chan, f->subclass, f->data, f->datalen);
 			}
diff --git a/apps/app_followme.c b/apps/app_followme.c
index 9dd130b9da..4e83c819f1 100644
--- a/apps/app_followme.c
+++ b/apps/app_followme.c
@@ -656,6 +656,9 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
 					case AST_CONTROL_VIDUPDATE:
 						ast_verb(3, "%s requested a video update, passing it to %s\n", winner->name, caller->name);
 						break;
+					case AST_CONTROL_SRCUPDATE:
+						ast_verb(3, "%s requested a source update, passing it to %s\n", winner->name, caller->name);
+						break;
 					case AST_CONTROL_PROCEEDING:
 						ast_verb(3, "%s is proceeding passing it to %s\n", winner->name,caller->name);
 						break;
diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c
index ec1107695e..3e9199fce4 100644
--- a/channels/chan_alsa.c
+++ b/channels/chan_alsa.c
@@ -510,6 +510,7 @@ static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, s
 	case AST_CONTROL_PROGRESS:
 	case AST_CONTROL_PROCEEDING:
 	case AST_CONTROL_VIDUPDATE:
+	case AST_CONTROL_SRCUPDATE:
 		break;
 	case AST_CONTROL_HOLD:
 		ast_verbose(" << Console Has Been Placed on Hold >> \n");
diff --git a/channels/chan_console.c b/channels/chan_console.c
index c558f5b1db..7d62e6235c 100644
--- a/channels/chan_console.c
+++ b/channels/chan_console.c
@@ -610,6 +610,7 @@ static int console_indicate(struct ast_channel *chan, int cond, const void *data
 	case AST_CONTROL_PROGRESS:
 	case AST_CONTROL_PROCEEDING:
 	case AST_CONTROL_VIDUPDATE:
+	case AST_CONTROL_SRCUPDATE:
 		break;
 	case AST_CONTROL_HOLD:
 		ast_verb(1, V_BEGIN "Console Has Been Placed on Hold" V_END);
diff --git a/channels/chan_h323.c b/channels/chan_h323.c
index e61fa101ad..2b1ef51e7c 100644
--- a/channels/chan_h323.c
+++ b/channels/chan_h323.c
@@ -914,6 +914,10 @@ static int oh323_indicate(struct ast_channel *c, int condition, const void *data
 		ast_moh_stop(c);
 		res = 0;
 		break;
+	case AST_CONTROL_SRCUPDATE:
+		ast_rtp_new_source(pvt->rtp);
+		res = 0;
+		break;
 	case AST_CONTROL_PROCEEDING:
 	case -1:
 		break;
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index f4ce2ce6a2..9f334298e9 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -1479,6 +1479,9 @@ static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, siz
 	case AST_CONTROL_UNHOLD:
 		ast_moh_stop(ast);
 		break;
+	case AST_CONTROL_SRCUPDATE:
+		ast_rtp_new_source(sub->rtp);
+		break;
 	case -1:
 		transmit_notify_request(sub, "");
 		break;
diff --git a/channels/chan_oss.c b/channels/chan_oss.c
index 4f40085fad..6269512086 100644
--- a/channels/chan_oss.c
+++ b/channels/chan_oss.c
@@ -764,6 +764,7 @@ static int oss_indicate(struct ast_channel *c, int cond, const void *data, size_
 	case AST_CONTROL_PROGRESS:
 	case AST_CONTROL_PROCEEDING:
 	case AST_CONTROL_VIDUPDATE:
+	case AST_CONTROL_SRCUPDATE:
 		break;
 	case AST_CONTROL_HOLD:
 		ast_verbose(" << Console Has Been Placed on Hold >> \n");
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index 233e5e8294..48b26c160d 100644
--- a/channels/chan_phone.c
+++ b/channels/chan_phone.c
@@ -206,21 +206,24 @@ static int phone_indicate(struct ast_channel *chan, int condition, const void *d
 	int res=-1;
 	ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
 	switch(condition) {
-		case AST_CONTROL_FLASH:
-			ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
-			usleep(320000);
-			ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
+	case AST_CONTROL_FLASH:
+		ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
+		usleep(320000);
+		ioctl(p->fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
 			p->lastformat = -1;
 			res = 0;
 			break;
-		case AST_CONTROL_HOLD:
-			ast_moh_start(chan, data, NULL);
-			break;
-		case AST_CONTROL_UNHOLD:
-			ast_moh_stop(chan);
-			break;
-		default:
-			ast_log(LOG_WARNING, "Condition %d is not supported on channel %s\n", condition, chan->name);
+	case AST_CONTROL_HOLD:
+		ast_moh_start(chan, data, NULL);
+		break;
+	case AST_CONTROL_UNHOLD:
+		ast_moh_stop(chan);
+		break;
+	case AST_CONTROL_SRCUPDATE:
+		res = 0;
+		break;
+	default:
+		ast_log(LOG_WARNING, "Condition %d is not supported on channel %s\n", condition, chan->name);
 	}
 	return res;
 }
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 4343583b2d..fa9052dfa6 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -5140,6 +5140,9 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
 			}
 		}
 		break;
+	case AST_CONTROL_SRCUPDATE:
+		ast_rtp_new_source(p->rtp);
+		break;
 	case -1:
 		res = -1;
 		break;
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 90a611bedf..44d88ae1f9 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -3650,6 +3650,9 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
 		break;
 	case AST_CONTROL_PROCEEDING:
 		break;
+	case AST_CONTROL_SRCUPDATE:
+		ast_rtp_new_source(sub->rtp);
+		break;
 	default:
 		ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
 		return -1;
diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c
index 923d5d4944..8adb3497b4 100644
--- a/channels/chan_unistim.c
+++ b/channels/chan_unistim.c
@@ -4117,6 +4117,7 @@ static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
 		ast_moh_stop(ast);
 		break;
 	case AST_CONTROL_PROGRESS:
+	case AST_CONTROL_SRCUPDATE:
 		break;
 	case -1:
 		ast_playtones_stop(ast);
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index 9e73eeffd5..ea19e9f56e 100644
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -5813,6 +5813,9 @@ static int zt_indicate(struct ast_channel *chan, int condition, const void *data
 			} else
 				res = 0;
 			break;
+		case AST_CONTROL_SRCUPDATE:
+			res = 0;
+			break;
 		case -1:
 			res = tone_zone_play_tone(p->subs[index].zfd, -1);
 			break;
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index 3206f860f8..ad4b829200 100644
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -83,6 +83,7 @@ struct ast_codec_pref {
 	\arg \b HOLD	Call is placed on hold
 	\arg \b UNHOLD	Call is back from hold
 	\arg \b VIDUPDATE	Video update requested
+	\arg \b SRCUPDATE       The source of media has changed
 
 */
 
@@ -292,7 +293,8 @@ enum ast_control_frame_type {
 	AST_CONTROL_HOLD = 16,		/*!< Indicate call is placed on hold */
 	AST_CONTROL_UNHOLD = 17,	/*!< Indicate call is left from hold */
 	AST_CONTROL_VIDUPDATE = 18,	/*!< Indicate video frame update */
-	AST_CONTROL_T38 = 19		/*!< T38 state change request/notification */
+	AST_CONTROL_T38 = 19,		/*!< T38 state change request/notification */
+	AST_CONTROL_SRCUPDATE = 20,     /*!< Indicate source of media has changed */
 };
 
 enum ast_control_t38 {
diff --git a/main/channel.c b/main/channel.c
index ecb12ac573..3c68a71b7c 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -2745,6 +2745,8 @@ int ast_indicate_data(struct ast_channel *chan, int condition, const void *data,
 				/* Do nothing.... */
 			} else if (condition == AST_CONTROL_VIDUPDATE) {
 				/* Do nothing.... */
+			} else if (condition == AST_CONTROL_SRCUPDATE) {
+				/* Do nothing... */
 			} else {
 				/* not handled */
 				ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
@@ -3272,6 +3274,7 @@ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *d
 				case AST_CONTROL_HOLD:
 				case AST_CONTROL_UNHOLD:
 				case AST_CONTROL_VIDUPDATE:
+				case AST_CONTROL_SRCUPDATE:
 				case -1:			/* Ignore -- just stopping indications */
 					break;
 
@@ -4156,6 +4159,7 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
 			case AST_CONTROL_HOLD:
 			case AST_CONTROL_UNHOLD:
 			case AST_CONTROL_VIDUPDATE:
+			case AST_CONTROL_SRCUPDATE:
 				ast_indicate_data(other, f->subclass, f->data, f->datalen);
 				break;
 			default:
@@ -4318,6 +4322,10 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
 		ast_set_flag(c0, AST_FLAG_END_DTMF_ONLY);
 	manager_bridge_event(1, 1, c0, c1);
 
+	/* Before we enter in and bridge these two together tell them both the source of audio has changed */
+	ast_indicate(c0, AST_CONTROL_SRCUPDATE);
+	ast_indicate(c1, AST_CONTROL_SRCUPDATE);
+
 	for (/* ever */;;) {
 		struct timeval now = { 0, };
 		int to;
@@ -4470,6 +4478,10 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
 	ast_clear_flag(c0, AST_FLAG_END_DTMF_ONLY);
 	ast_clear_flag(c1, AST_FLAG_END_DTMF_ONLY);
 
+	/* Now that we have broken the bridge the source will change yet again */
+	ast_indicate(c0, AST_CONTROL_SRCUPDATE);
+	ast_indicate(c1, AST_CONTROL_SRCUPDATE);
+
 	c0->_bridge = NULL;
 	c1->_bridge = NULL;
 
diff --git a/main/dial.c b/main/dial.c
index 22472a89e4..688382fb86 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -422,6 +422,10 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
 			ast_verb(3, "%s requested a video update, passing it to %s\n", channel->owner->name, chan->name);
 			ast_indicate(chan, AST_CONTROL_VIDUPDATE);
 			break;
+		case AST_CONTROL_SRCUPDATE:
+			if (option_verbose > 2)
+				ast_verbose (VERBOSE_PREFIX_3 "%s requested a source update, passing it to %s\n", channel->owner->name, chan->name);
+			ast_indicate(chan, AST_CONTROL_SRCUPDATE);
 		case AST_CONTROL_PROCEEDING:
 			ast_verb(3, "%s is proceeding, passing it to %s\n", channel->owner->name, chan->name);
 			ast_indicate(chan, AST_CONTROL_PROCEEDING);
diff --git a/main/file.c b/main/file.c
index c16f25112e..16fe39e777 100644
--- a/main/file.c
+++ b/main/file.c
@@ -1136,6 +1136,7 @@ static int waitstream_core(struct ast_channel *c, const char *breakon,
 				case AST_CONTROL_RINGING:
 				case AST_CONTROL_ANSWER:
 				case AST_CONTROL_VIDUPDATE:
+				case AST_CONTROL_SRCUPDATE:
 				case AST_CONTROL_HOLD:
 				case AST_CONTROL_UNHOLD:
 					/* Unimportant */
diff --git a/main/rtp.c b/main/rtp.c
index 5be0586c6e..433fa2c79a 100644
--- a/main/rtp.c
+++ b/main/rtp.c
@@ -3376,7 +3376,8 @@ static enum ast_bridge_result bridge_native_loop(struct ast_channel *c0, struct
 			if ((fr->subclass == AST_CONTROL_HOLD) ||
 			    (fr->subclass == AST_CONTROL_UNHOLD) ||
 			    (fr->subclass == AST_CONTROL_VIDUPDATE) ||
-			    (fr->subclass == AST_CONTROL_T38)) {
+			    (fr->subclass == AST_CONTROL_T38) ||
+			    (fr->subclass == AST_CONTROL_SRCUPDATE)) {
 				if (fr->subclass == AST_CONTROL_HOLD) {
 					/* If we someone went on hold we want the other side to reinvite back to us */
 					if (who == c0)
@@ -3615,7 +3616,8 @@ static enum ast_bridge_result bridge_p2p_loop(struct ast_channel *c0, struct ast
 			if ((fr->subclass == AST_CONTROL_HOLD) ||
 			    (fr->subclass == AST_CONTROL_UNHOLD) ||
 			    (fr->subclass == AST_CONTROL_VIDUPDATE) ||
-			    (fr->subclass == AST_CONTROL_T38)) {
+			    (fr->subclass == AST_CONTROL_T38) ||
+			    (fr->subclass == AST_CONTROL_SRCUPDATE)) {
 				/* If we are going on hold, then break callback mode and P2P bridging */
 				if (fr->subclass == AST_CONTROL_HOLD) {
 					if (p0_callback)
-- 
GitLab