/*! \internal \brief Disable talk detection on the channel */ static int remove_talk_detect(struct ast_channel *chan) { struct ast_datastore *datastore = NULL; struct talk_detect_params *td_params; SCOPED_CHANNELLOCK(chan_lock, chan); datastore = ast_channel_datastore_find(chan, &talk_detect_datastore, NULL); if (!datastore) { ast_log(AST_LOG_WARNING, "Cannot remove TALK_DETECT from %s: TALK_DETECT not currently enabled\n", ast_channel_name(chan)); return -1; } td_params = datastore->data; if (ast_audiohook_remove(chan, &td_params->audiohook)) { ast_log(AST_LOG_WARNING, "Failed to remove TALK_DETECT audiohook from channel %s\n", ast_channel_name(chan)); return -1; } if (ast_channel_datastore_remove(chan, datastore)) { ast_log(AST_LOG_WARNING, "Failed to remove TALK_DETECT datastore from channel %s\n", ast_channel_name(chan)); return -1; } ast_datastore_free(datastore); return 0; }
/*! \brief Helper function which gets the format for a Snoop channel based on the channel being snooped on */ static void snoop_determine_format(struct ast_channel *chan, struct stasis_app_snoop *snoop) { SCOPED_CHANNELLOCK(lock, chan); unsigned int rate = MAX(ast_format_get_sample_rate(ast_channel_rawwriteformat(chan)), ast_format_get_sample_rate(ast_channel_rawreadformat(chan))); snoop->spy_format = ast_format_cache_get_slin_by_rate(rate); }
static int app_control_unmute(struct stasis_app_control *control, struct ast_channel *chan, void *data) { RAII_VAR(struct stasis_app_control_mute_data *, mute_data, data, ast_free); SCOPED_CHANNELLOCK(lockvar, chan); ast_channel_unsuppress(control->channel, mute_data->direction, mute_data->frametype); return 0; }
static int app_control_mute(struct stasis_app_control *control, struct ast_channel *chan, void *data) { struct stasis_app_control_mute_data *mute_data = data; SCOPED_CHANNELLOCK(lockvar, chan); ast_channel_suppress(control->channel, mute_data->direction, mute_data->frametype); return 0; }
/*! \internal \brief Enable talk detection on the channel */ static int set_talk_detect(struct ast_channel *chan, int dsp_silence_threshold, int dsp_talking_threshold) { struct ast_datastore *datastore = NULL; struct talk_detect_params *td_params; SCOPED_CHANNELLOCK(chan_lock, chan); datastore = ast_channel_datastore_find(chan, &talk_detect_datastore, NULL); if (!datastore) { datastore = ast_datastore_alloc(&talk_detect_datastore, NULL); if (!datastore) { return -1; } td_params = ast_calloc(1, sizeof(*td_params)); if (!td_params) { ast_datastore_free(datastore); return -1; } ast_audiohook_init(&td_params->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "TALK_DETECT", AST_AUDIOHOOK_MANIPULATE_ALL_RATES); td_params->audiohook.manipulate_callback = talk_detect_audiohook_cb; ast_set_flag(&td_params->audiohook, AST_AUDIOHOOK_TRIGGER_READ); td_params->dsp = ast_dsp_new_with_rate(ast_format_get_sample_rate(ast_channel_rawreadformat(chan))); if (!td_params->dsp) { ast_datastore_free(datastore); ast_free(td_params); return -1; } datastore->data = td_params; ast_channel_datastore_add(chan, datastore); ast_audiohook_attach(chan, &td_params->audiohook); } else { /* Talk detection already enabled; update existing settings */ td_params = datastore->data; } td_params->dsp_talking_threshold = dsp_talking_threshold; td_params->dsp_silence_threshold = dsp_silence_threshold; ast_dsp_set_threshold(td_params->dsp, td_params->dsp_talking_threshold); return 0; }
char *stasis_app_control_get_channel_var(struct stasis_app_control *control, const char *variable) { RAII_VAR(struct ast_str *, tmp, ast_str_create(32), ast_free); SCOPED_CHANNELLOCK(lockvar, control->channel); if (!tmp) { return NULL; } if (variable[strlen(variable) - 1] == ')') { if (ast_func_read2(control->channel, variable, &tmp, 0)) { return NULL; } } else { if (!ast_str_retrieve_variable(&tmp, 0, control->channel, NULL, variable)) { return NULL; } } return ast_strdup(ast_str_buffer(tmp)); }
int conf_announce_channel_push(struct ast_channel *ast) { struct ast_bridge_features *features; struct ast_channel *chan; RAII_VAR(struct announce_pvt *, p, NULL, ao2_cleanup); { SCOPED_CHANNELLOCK(lock, ast); p = ast_channel_tech_pvt(ast); if (!p) { return -1; } ao2_ref(p, +1); chan = p->base.chan; if (!chan) { return -1; } ast_channel_ref(chan); } features = ast_bridge_features_new(); if (!features) { ast_channel_unref(chan); return -1; } ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE); /* Impart the output channel into the bridge */ if (ast_bridge_impart(p->bridge, chan, NULL, features, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)) { ast_bridge_features_destroy(features); ast_channel_unref(chan); return -1; } ao2_lock(p); ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD); ao2_unlock(p); return 0; }
static int bridge_channel_depart(struct stasis_app_control *control, struct ast_channel *chan, void *data) { RAII_VAR(struct ast_bridge_channel *, bridge_channel, data, ao2_cleanup); { SCOPED_CHANNELLOCK(lock, chan); if (bridge_channel != ast_channel_internal_bridge_channel(chan)) { ast_debug(3, "%s: Channel is no longer in departable state\n", ast_channel_uniqueid(chan)); return -1; } } ast_debug(3, "%s: Channel departing bridge\n", ast_channel_uniqueid(chan)); ast_bridge_depart(chan); return 0; }
static enum set_touch_variables_res set_touch_variables(struct ast_channel *chan, int is_mixmonitor, char **touch_format, char **touch_monitor, char **touch_monitor_prefix) { enum set_touch_variables_res res = SET_TOUCH_UNSET; const char *var_format; const char *var_monitor; const char *var_prefix; SCOPED_CHANNELLOCK(lock, chan); if (is_mixmonitor) { var_format = "TOUCH_MIXMONITOR_FORMAT"; var_monitor = "TOUCH_MIXMONITOR"; var_prefix = "TOUCH_MIXMONITOR_PREFIX"; } else { var_format = "TOUCH_MONITOR_FORMAT"; var_monitor = "TOUCH_MONITOR"; var_prefix = "TOUCH_MONITOR_PREFIX"; } set_touch_variable(&res, chan, var_format, touch_format); set_touch_variable(&res, chan, var_monitor, touch_monitor); set_touch_variable(&res, chan, var_prefix, touch_monitor_prefix); return res; }
int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge, unsigned int flags) { struct ast_bridge_features *features; struct ast_channel *chan; struct ast_channel *owner; RAII_VAR(struct ast_unreal_pvt *, p, NULL, ao2_cleanup); RAII_VAR(struct ast_callid *, bridge_callid, NULL, ast_callid_cleanup); ast_bridge_lock(bridge); bridge_callid = bridge->callid ? ast_callid_ref(bridge->callid) : NULL; ast_bridge_unlock(bridge); { SCOPED_CHANNELLOCK(lock, ast); p = ast_channel_tech_pvt(ast); if (!p) { return -1; } ao2_ref(p, +1); } { SCOPED_AO2LOCK(lock, p); chan = p->chan; if (!chan) { return -1; } owner = p->owner; if (!owner) { return -1; } ast_channel_ref(chan); ast_channel_ref(owner); } if (bridge_callid) { struct ast_callid *chan_callid; struct ast_callid *owner_callid; /* chan side call ID setting */ ast_channel_lock(chan); chan_callid = ast_channel_callid(chan); if (!chan_callid) { ast_channel_callid_set(chan, bridge_callid); } ast_channel_unlock(chan); ast_callid_cleanup(chan_callid); /* owner side call ID setting */ ast_channel_lock(owner); owner_callid = ast_channel_callid(owner); if (!owner_callid) { ast_channel_callid_set(owner, bridge_callid); } ast_channel_unlock(owner); ast_callid_cleanup(owner_callid); } /* We are done with the owner now that its call ID matches the bridge */ ast_channel_unref(owner); owner = NULL; features = ast_bridge_features_new(); if (!features) { ast_channel_unref(chan); return -1; } ast_set_flag(&features->feature_flags, flags); /* Impart the semi2 channel into the bridge */ if (ast_bridge_impart(bridge, chan, NULL, features, AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_bridge_features_destroy(features); ast_channel_unref(chan); return -1; } ao2_lock(p); ast_set_flag(p, AST_UNREAL_CARETAKER_THREAD); ao2_unlock(p); ast_channel_unref(chan); return 0; }