[Asterisk-code-review] ari/bridge: Add mute, dtmf suppression controls (asterisk[master])

Seán C. McCord asteriskteam at digium.com
Fri Oct 6 20:50:24 CDT 2017


Seán C. McCord has uploaded this change for review. ( https://gerrit.asterisk.org/6675


Change subject: ari/bridge: Add mute, dtmf suppression controls
......................................................................

ari/bridge: Add mute, dtmf suppression controls

Add bridge_features structure to bridge creation.  Specifically, this
implements mute and DTMF suppression, but others should be able to be
easily added to the same structure.

ASTERISK-27322 #close
Reported by: Darren Sessions
Sponsored by: AVOXI

Change-Id: Id4002adfb65c9a8027ee9e1a5f477e0f01cf9d61
---
M include/asterisk/stasis_app.h
M res/ari/resource_bridges.c
M res/ari/resource_bridges.h
M res/res_ari_bridges.c
M res/stasis/control.c
M rest-api/api-docs/bridges.json
6 files changed, 122 insertions(+), 1 deletion(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/75/6675/1

diff --git a/include/asterisk/stasis_app.h b/include/asterisk/stasis_app.h
index ca5c251..d0ae5d8 100644
--- a/include/asterisk/stasis_app.h
+++ b/include/asterisk/stasis_app.h
@@ -793,6 +793,38 @@
 	struct stasis_app_control *control, struct ast_bridge *bridge);
 
 /*!
+ * \brief Initialize bridge features into a channel control
+ *
+ * \note Bridge features on a control are destroyed after each bridge session,
+ *       so new features need to be initialized before each bridge add.
+ *
+ * \param control Control in which to store the features
+ *
+ * \return non-zero on failure
+ * \return zero on success
+ */
+int stasis_app_control_bridge_features_init(
+	struct stasis_app_control *control);
+
+/*!
+ * \brief Set whether DTMF from the channel is absorbed instead of passing through to the bridge
+ *
+ * \param control Control whose channel should have its DTMF absorbed when bridged
+ * \param absorb Whether DTMF should be absorbed (1) instead of passed through (0).
+ */
+void stasis_app_control_absorb_dtmf_in_bridge(
+	struct stasis_app_control *control, int absorb);
+
+/*!
+ * \brief Set whether audio from the channel is muted instead of passing through to the bridge
+ *
+ * \param control Control whose channel should have its audio muted when bridged
+ * \param absorb Whether audio should be muted (1) instead of passed through (0).
+ */
+void stasis_app_control_mute_in_bridge(
+	struct stasis_app_control *control, int mute);
+
+/*!
  * \since 12
  * \brief Gets the bridge currently associated with a control object.
  *
diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c
index f243086..39772a6 100644
--- a/res/ari/resource_bridges.c
+++ b/res/ari/resource_bridges.c
@@ -199,6 +199,7 @@
 	size_t i;
 	int has_error = 0;
 
+
 	if (!bridge) {
 		/* Response filled in by find_bridge() */
 		return;
@@ -220,6 +221,14 @@
 		}
 	}
 
+   /* Apply bridge features to each of the channel controls */
+   for (i = 0; i < list->count; ++i) {
+      if(!stasis_app_control_bridge_features_init(list->controls[i])) {
+         stasis_app_control_absorb_dtmf_in_bridge(list->controls[i], args->absorb_dtmf);
+         stasis_app_control_mute_in_bridge(list->controls[i], args->mute);
+      }
+   }
+
 	for (i = 0; i < list->count; ++i) {
 		if ((has_error = check_add_remove_channel(response, list->controls[i],
 			     stasis_app_control_add_channel_to_bridge(
diff --git a/res/ari/resource_bridges.h b/res/ari/resource_bridges.h
index e75d8e0..72dba1e 100644
--- a/res/ari/resource_bridges.h
+++ b/res/ari/resource_bridges.h
@@ -150,6 +150,10 @@
 	char *channel_parse;
 	/*! Channel's role in the bridge */
 	const char *role;
+	/*! Absorb DTMF coming from this channel, preventing it to pass through to the bridge */
+	int absorb_dtmf;
+	/*! Mute audio from this channel, preventing it to pass through to the bridge */
+	int mute;
 };
 /*!
  * \brief Body parsing function for /bridges/{bridgeId}/addChannel.
diff --git a/res/res_ari_bridges.c b/res/res_ari_bridges.c
index 65bf7ed..35fd3bd 100644
--- a/res/res_ari_bridges.c
+++ b/res/res_ari_bridges.c
@@ -430,6 +430,14 @@
 	if (field) {
 		args->role = ast_json_string_get(field);
 	}
+	field = ast_json_object_get(body, "absorbDTMF");
+	if (field) {
+		args->absorb_dtmf = ast_json_is_true(field);
+	}
+	field = ast_json_object_get(body, "mute");
+	if (field) {
+		args->mute = ast_json_is_true(field);
+	}
 	return 0;
 }
 
@@ -499,6 +507,12 @@
 		if (strcmp(i->name, "role") == 0) {
 			args.role = (i->value);
 		} else
+		if (strcmp(i->name, "absorbDTMF") == 0) {
+			args.absorb_dtmf = ast_true(i->value);
+		} else
+		if (strcmp(i->name, "mute") == 0) {
+			args.mute = ast_true(i->value);
+		} else
 		{}
 	}
 	for (i = path_vars; i; i = i->next) {
diff --git a/res/stasis/control.c b/res/stasis/control.c
index 01c04df..756955a 100644
--- a/res/stasis/control.c
+++ b/res/stasis/control.c
@@ -35,6 +35,7 @@
 #include "asterisk/bridge.h"
 #include "asterisk/bridge_after.h"
 #include "asterisk/bridge_basic.h"
+#include "asterisk/bridge_features.h"
 #include "asterisk/frame.h"
 #include "asterisk/pbx.h"
 #include "asterisk/musiconhold.h"
@@ -61,6 +62,10 @@
 	 * When a channel is in a bridge, the bridge that it is in.
 	 */
 	struct ast_bridge *bridge;
+	/*!
+	 * Bridge features which should be applied to the channel when it enters the next bridge.  These only apply to the next bridge and will be emptied thereafter.
+	 */
+	struct ast_bridge_features *bridge_features;
 	/*!
 	 * Holding place for channel's PBX while imparted to a bridge.
 	 */
@@ -99,6 +104,7 @@
 	ast_cond_destroy(&control->wait_cond);
 	AST_LIST_HEAD_DESTROY(&control->add_rules);
 	AST_LIST_HEAD_DESTROY(&control->remove_rules);
+
 }
 
 struct stasis_app_control *control_create(struct ast_channel *channel, struct stasis_app *app)
@@ -126,6 +132,8 @@
 
 	ast_channel_ref(channel);
 	control->channel = channel;
+
+   control->bridge_features = NULL;
 
 	control->command_queue = ao2_container_alloc_list(
 		AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, NULL);
@@ -1161,10 +1169,15 @@
 int control_swap_channel_in_bridge(struct stasis_app_control *control, struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap)
 {
 	int res;
+   struct ast_bridge_features *features;
 
 	if (!control || !bridge) {
 		return -1;
 	}
+
+   /* Pull bridge features from the control */
+   features = control->bridge_features;
+   control->bridge_features = NULL;
 
 	ast_debug(3, "%s: Adding to bridge %s\n",
 		stasis_app_control_get_channel_id(control),
@@ -1220,7 +1233,7 @@
 	res = ast_bridge_impart(bridge,
 		chan,
 		swap,
-		NULL, /* features */
+		features, /* features */
 		AST_BRIDGE_IMPART_CHAN_DEPARTABLE);
 	if (res != 0) {
 		/* ast_bridge_impart failed before it could spawn the depart
@@ -1316,6 +1329,37 @@
 	return ast_queue_control(control->channel, frame_type);
 }
 
+int stasis_app_control_bridge_features_init(
+      struct stasis_app_control *control)
+{
+   struct ast_bridge_features *features;
+
+   features = ast_bridge_features_new();
+   if (!features) {
+      ast_log(LOG_ERROR, "Error initializing bridge_features: %s\n",
+            strerror(errno));
+      return 1;
+   }
+   control->bridge_features = features;
+   return 0;
+}
+
+void stasis_app_control_absorb_dtmf_in_bridge(
+      struct stasis_app_control *control, int absorb)
+{
+   if (absorb == 1) {
+      control->bridge_features->dtmf_passthrough = 0;
+   } else {
+      control->bridge_features->dtmf_passthrough = 1;
+   }
+}
+
+void stasis_app_control_mute_in_bridge(
+      struct stasis_app_control *control, int mute)
+{
+   control->bridge_features->mute = mute;
+}
+
 void control_flush_queue(struct stasis_app_control *control)
 {
 	struct ao2_iterator iter;
diff --git a/rest-api/api-docs/bridges.json b/rest-api/api-docs/bridges.json
index 877fdf8..88bb97e 100644
--- a/rest-api/api-docs/bridges.json
+++ b/rest-api/api-docs/bridges.json
@@ -169,6 +169,24 @@
 							"required": false,
 							"allowMultiple": false,
 							"dataType": "string"
+						},
+						{
+							"name": "absorbDTMF",
+							"description": "Absorb DTMF coming from this channel, preventing it to pass through to the bridge",
+							"paramType": "query",
+							"required": false,
+							"allowMultiple": false,
+							"dataType": "boolean",
+                     "defaultValue": false
+						},
+						{
+							"name": "mute",
+							"description": "Mute audio from this channel, preventing it to pass through to the bridge",
+							"paramType": "query",
+							"required": false,
+							"allowMultiple": false,
+							"dataType": "boolean",
+                     "defaultValue": false
 						}
 					],
 					"errorResponses": [

-- 
To view, visit https://gerrit.asterisk.org/6675
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Id4002adfb65c9a8027ee9e1a5f477e0f01cf9d61
Gerrit-Change-Number: 6675
Gerrit-PatchSet: 1
Gerrit-Owner: Seán C. McCord <ulexus at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20171006/f0565550/attachment-0001.html>


More information about the asterisk-code-review mailing list