|
|
|
@ -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 @@ struct stasis_app_control {
|
|
|
|
|
* 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,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;
|
|
|
|
|