diff options
author | Seán C McCord <ulexus@gmail.com> | 2017-10-06 21:48:48 -0400 |
---|---|---|
committer | Seán C McCord <ulexus@gmail.com> | 2017-10-11 08:23:05 -0400 |
commit | e8bde6916ab0003e6737a320074b1c6ae1516db0 (patch) | |
tree | 6e08df9a01a8d0a5bfe3792730a79cf9051d9a78 | |
parent | 1505c1bb09987b36c4c55d1ab6d95e57d0fede16 (diff) |
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
-rw-r--r-- | include/asterisk/stasis_app.h | 32 | ||||
-rw-r--r-- | res/ari/resource_bridges.c | 6 | ||||
-rw-r--r-- | res/ari/resource_bridges.h | 4 | ||||
-rw-r--r-- | res/res_ari_bridges.c | 14 | ||||
-rw-r--r-- | res/stasis/control.c | 39 | ||||
-rw-r--r-- | rest-api/api-docs/bridges.json | 18 |
6 files changed, 112 insertions, 1 deletions
diff --git a/include/asterisk/stasis_app.h b/include/asterisk/stasis_app.h index ca5c25111..8ef2bda1c 100644 --- a/include/asterisk/stasis_app.h +++ b/include/asterisk/stasis_app.h @@ -793,6 +793,38 @@ int stasis_app_control_remove_channel_from_bridge( 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 mute 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 f243086c9..aab78ce18 100644 --- a/res/ari/resource_bridges.c +++ b/res/ari/resource_bridges.c @@ -218,6 +218,12 @@ void ast_ari_bridges_add_channel(struct ast_variable *headers, return; } } + + /* Apply bridge features to each of the channel controls */ + 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) { diff --git a/res/ari/resource_bridges.h b/res/ari/resource_bridges.h index e75d8e028..72dba1e0c 100644 --- a/res/ari/resource_bridges.h +++ b/res/ari/resource_bridges.h @@ -150,6 +150,10 @@ struct ast_ari_bridges_add_channel_args { 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 65bf7ed3e..35fd3bd7f 100644 --- a/res/res_ari_bridges.c +++ b/res/res_ari_bridges.c @@ -430,6 +430,14 @@ int ast_ari_bridges_add_channel_parse_body( 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 @@ static void ast_ari_bridges_add_channel_cb( 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 01c04dffe..dc005a1e5 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" @@ -62,6 +63,10 @@ struct stasis_app_control { */ 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. */ struct ast_pbx *pbx; @@ -99,6 +104,8 @@ static void control_dtor(void *obj) ast_cond_destroy(&control->wait_cond); AST_LIST_HEAD_DESTROY(&control->add_rules); AST_LIST_HEAD_DESTROY(&control->remove_rules); + ast_bridge_features_destroy(control->bridge_features); + } struct stasis_app_control *control_create(struct ast_channel *channel, struct stasis_app *app) @@ -1161,6 +1168,7 @@ static void set_interval_hook(struct ast_channel *chan) 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; @@ -1205,6 +1213,10 @@ int control_swap_channel_in_bridge(struct stasis_app_control *control, struct as ast_channel_pbx_set(chan, NULL); } + /* Pull bridge features from the control */ + features = control->bridge_features; + control->bridge_features = NULL; + ast_assert(stasis_app_get_bridge(control) == NULL); /* We need to set control->bridge here since bridge_after_cb may be run * before ast_bridge_impart returns. bridge_after_cb gets a reason @@ -1220,7 +1232,7 @@ int control_swap_channel_in_bridge(struct stasis_app_control *control, struct as 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 +1328,31 @@ int stasis_app_control_queue_control(struct stasis_app_control *control, 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) { + return 1; + } + control->bridge_features = features; + return 0; +} + +void stasis_app_control_absorb_dtmf_in_bridge( + struct stasis_app_control *control, int absorb) +{ + control->bridge_features->dtmf_passthrough = !absorb; +} + +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 877fdf84d..cf8ee3156 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": [ |