summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/app_confbridge.c44
-rw-r--r--apps/confbridge/conf_config_parser.c246
-rw-r--r--apps/confbridge/include/confbridge.h60
3 files changed, 253 insertions, 97 deletions
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index 6f1420fcd..d16011b1d 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -100,8 +100,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
</parameter>
<parameter name="menu">
<para>The name of the DTMF menu in confbridge.conf to be applied to
- this channel. No menu is applied by default if this option is left
- blank.</para>
+ this channel. When left blank, a dynamically built menu profile
+ created by the CONFBRIDGE dialplan function is searched for on
+ the channel and used. If no dynamic profile is present, the
+ 'default_menu' profile found in confbridge.conf is used.</para>
</parameter>
</syntax>
<description>
@@ -116,14 +118,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
</application>
<function name="CONFBRIDGE" language="en_US">
<synopsis>
- Set a custom dynamic bridge and user profile on a channel for the ConfBridge application using the same options defined in confbridge.conf.
+ Set a custom dynamic bridge, user, or menu profile on a channel for the ConfBridge application using the same options defined in confbridge.conf.
</synopsis>
<syntax>
<parameter name="type" required="true">
- <para>Type refers to which type of profile the option belongs too. Type can be <literal>bridge</literal> or <literal>user</literal>.</para>
+ <para>Type refers to which type of profile the option belongs too. Type can be <literal>bridge</literal>, <literal>user</literal>, or
+ <literal>menu</literal>.</para>
</parameter>
<parameter name="option" required="true">
- <para>Option refers to <filename>confbridge.conf</filename> option that is being set dynamically on this channel.</para>
+ <para>Option refers to <filename>confbridge.conf</filename> option that is being set dynamically on this channel, or
+ <literal>clear</literal> to remove already applied options from the channel.</para>
</parameter>
</syntax>
<description>
@@ -1504,8 +1508,9 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
int res = 0, volume_adjustments[2];
int quiet = 0;
char *parse;
- const char *b_profile_name = DEFAULT_BRIDGE_PROFILE;
- const char *u_profile_name = DEFAULT_USER_PROFILE;
+ const char *b_profile_name = NULL;
+ const char *u_profile_name = NULL;
+ const char *menu_profile_name = NULL;
struct confbridge_conference *conference = NULL;
struct confbridge_user user = {
.chan = chan,
@@ -1517,7 +1522,7 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
AST_APP_ARG(conf_name);
AST_APP_ARG(b_profile_name);
AST_APP_ARG(u_profile_name);
- AST_APP_ARG(menu_name);
+ AST_APP_ARG(menu_profile_name);
);
if (ast_channel_state(chan) != AST_STATE_UP) {
@@ -1545,7 +1550,8 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
b_profile_name = args.b_profile_name;
}
if (!conf_find_bridge_profile(chan, b_profile_name, &user.b_profile)) {
- ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name);
+ ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name ?
+ b_profile_name : DEFAULT_BRIDGE_PROFILE);
res = -1;
goto confbridge_cleanup;
}
@@ -1555,7 +1561,8 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
u_profile_name = args.u_profile_name;
}
if (!conf_find_user_profile(chan, u_profile_name, &user.u_profile)) {
- ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name);
+ ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name ?
+ u_profile_name : DEFAULT_USER_PROFILE);
res = -1;
goto confbridge_cleanup;
}
@@ -1577,14 +1584,15 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
}
/* menu name */
- if (args.argc > 3 && !ast_strlen_zero(args.menu_name)) {
- ast_copy_string(user.menu_name, args.menu_name, sizeof(user.menu_name));
- if (conf_set_menu_to_user(user.menu_name, &user)) {
- ast_log(LOG_WARNING, "Conference menu %s does not exist and can not be applied to confbridge user.\n",
- args.menu_name);
- res = -1; /* invalid PIN */
- goto confbridge_cleanup;
- }
+ if (args.argc > 3 && !ast_strlen_zero(args.menu_profile_name)) {
+ menu_profile_name = args.menu_profile_name;
+ }
+
+ if (conf_set_menu_to_user(chan, &user, menu_profile_name)) {
+ ast_log(LOG_WARNING, "Conference menu profile %s does not exist\n", menu_profile_name ?
+ menu_profile_name : DEFAULT_MENU_PROFILE);
+ res = -1;
+ goto confbridge_cleanup;
}
/* Set if DTMF should pass through for this user or not */
diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c
index 97c0696a7..5c430ea3a 100644
--- a/apps/confbridge/conf_config_parser.c
+++ b/apps/confbridge/conf_config_parser.c
@@ -419,6 +419,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
</enumlist>
</description>
</configOption>
+ <configOption name="template">
+ <synopsis>When using the CONFBRIDGE dialplan function, use a menu profile as a template for creating a new temporary profile</synopsis>
+ </configOption>
<configOption name="^[0-9A-D*#]+$">
<synopsis>DTMF sequences to assign various confbridge actions to</synopsis>
<description>
@@ -896,15 +899,25 @@ static int set_sound(const char *sound_name, const char *sound_file, struct brid
struct func_confbridge_data {
struct bridge_profile b_profile;
struct user_profile u_profile;
+ struct conf_menu *menu;
unsigned int b_usable:1; /*!< Tells if bridge profile is usable or not */
unsigned int u_usable:1; /*!< Tells if user profile is usable or not */
+ unsigned int m_usable:1; /*!< Tells if menu profile is usable or not */
};
-static void func_confbridge_destroy_cb(void *data)
+
+static void func_confbridge_data_destructor(struct func_confbridge_data *b_data)
{
- struct func_confbridge_data *b_data = data;
conf_bridge_profile_destroy(&b_data->b_profile);
+ ao2_cleanup(b_data->menu);
ast_free(b_data);
+}
+
+static void func_confbridge_destroy_cb(void *data)
+{
+ struct func_confbridge_data *b_data = data;
+ func_confbridge_data_destructor(b_data);
};
+
static const struct ast_datastore_info confbridge_datastore = {
.type = "confbridge",
.destroy = func_confbridge_destroy_cb
@@ -944,14 +957,18 @@ int func_confbridge_helper(struct ast_channel *chan, const char *cmd, char *data
ast_datastore_free(datastore);
return 0;
}
+ datastore->data = b_data;
b_data->b_profile.sounds = bridge_profile_sounds_alloc();
if (!b_data->b_profile.sounds) {
ast_channel_unlock(chan);
ast_datastore_free(datastore);
- ast_free(b_data);
return 0;
}
- datastore->data = b_data;
+ if (!(b_data->menu = menu_alloc("dialplan"))) {
+ ast_channel_unlock(chan);
+ ast_datastore_free(datastore);
+ return 0;
+ }
ast_channel_datastore_add(chan, datastore);
} else {
b_data = datastore->data;
@@ -966,15 +983,48 @@ int func_confbridge_helper(struct ast_channel *chan, const char *cmd, char *data
tmpvar.value = value;
tmpvar.file = "CONFBRIDGE";
if (!strcasecmp(args.type, "bridge")) {
- if (!aco_process_var(&bridge_type, "dialplan", &tmpvar, &b_data->b_profile)) {
+ if (!strcasecmp(args.option, "clear")) {
+ b_data->b_usable = 0;
+ conf_bridge_profile_destroy(&b_data->b_profile);
+ memset(&b_data->b_profile, 0, sizeof(b_data->b_profile)) ;
+ if (!(b_data->b_profile.sounds = bridge_profile_sounds_alloc())) {
+ /* If this reallocation fails, the datastore has become unusable and must be destroyed. */
+ ast_channel_lock(chan);
+ ast_channel_datastore_remove(chan, datastore);
+ ast_channel_unlock(chan);
+ ast_datastore_free(datastore);
+ }
+ return 0;
+ } else if (!aco_process_var(&bridge_type, "dialplan", &tmpvar, &b_data->b_profile)) {
b_data->b_usable = 1;
return 0;
}
} else if (!strcasecmp(args.type, "user")) {
- if (!aco_process_var(&user_type, "dialplan", &tmpvar, &b_data->u_profile)) {
+ if (!strcasecmp(args.option, "clear")) {
+ b_data->u_usable = 0;
+ user_profile_destructor(&b_data->u_profile);
+ memset(&b_data->u_profile, 0, sizeof(b_data->u_profile));
+ return 0;
+ } else if (!aco_process_var(&user_type, "dialplan", &tmpvar, &b_data->u_profile)) {
b_data->u_usable = 1;
return 0;
}
+ } else if (!strcasecmp(args.type, "menu")) {
+ if (!strcasecmp(args.option, "clear")) {
+ b_data->m_usable = 0;
+ ao2_cleanup(b_data->menu);
+ if (!(b_data->menu = menu_alloc("dialplan"))) {
+ /* If this reallocation fails, the datastore has become unusable and must be destroyed */
+ ast_channel_lock(chan);
+ ast_channel_datastore_remove(chan, datastore);
+ ast_channel_unlock(chan);
+ ast_datastore_free(datastore);
+ }
+ return 0;
+ } else if (!aco_process_var(&menu_type, "dialplan", &tmpvar, b_data->menu)) {
+ b_data->m_usable = 1;
+ return 0;
+ }
}
ast_log(LOG_WARNING, "%s(%s,%s) cannot be set to '%s'. Invalid type, option, or value.\n",
@@ -1852,6 +1902,70 @@ static int bridge_template_handler(const struct aco_option *opt, struct ast_vari
return 0;
}
+static int copy_menu_entry(struct conf_menu_entry *dst, struct conf_menu_entry *src)
+{
+ struct conf_menu_action *menu_action;
+ struct conf_menu_action *new_menu_action;
+
+ ast_copy_string(dst->dtmf, src->dtmf, sizeof(dst->dtmf));
+ AST_LIST_HEAD_INIT_NOLOCK(&dst->actions);
+
+ AST_LIST_TRAVERSE(&src->actions, menu_action, action) {
+ if (!(new_menu_action = ast_calloc(1, sizeof(*new_menu_action)))) {
+ return -1;
+ }
+ memcpy(new_menu_action, menu_action, sizeof(*new_menu_action));
+ AST_LIST_NEXT(new_menu_action, action) = NULL;
+ AST_LIST_INSERT_TAIL(&dst->actions, new_menu_action, action);
+ }
+
+ return 0;
+}
+
+static int conf_menu_profile_copy(struct conf_menu *dst, struct conf_menu *src)
+{
+ /* Copy each menu item to the dst struct */
+ struct conf_menu_entry *cur;
+
+ AST_LIST_TRAVERSE(&src->entries, cur, entry) {
+ struct conf_menu_entry *cpy;
+
+ if (!(cpy = ast_calloc(1, sizeof(*cpy)))) {
+ return -1;
+ }
+
+ if (copy_menu_entry(cpy, cur)) {
+ conf_menu_entry_destroy(cpy);
+ ast_free(cpy);
+ return -1;
+ }
+ AST_LIST_INSERT_TAIL(&dst->entries, cpy, entry);
+ }
+
+ return 0;
+}
+
+static int menu_template_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+ struct conf_menu *dst_menu = obj;
+ struct confbridge_cfg *cfg = aco_pending_config(&cfg_info);
+ RAII_VAR(struct conf_menu *, src_menu, NULL, ao2_cleanup);
+
+ if (!cfg) {
+ return 0;
+ }
+
+ if (!(src_menu = ao2_find(cfg->menus, var->value, OBJ_KEY))) {
+ return -1;
+ }
+
+ if (conf_menu_profile_copy(dst_menu, src_menu)) {
+ return -1;
+ }
+
+ return 0;
+}
+
static int sound_option_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
set_sound(var->name, var->value, obj);
@@ -1868,6 +1982,7 @@ static int verify_default_profiles(void)
{
RAII_VAR(struct user_profile *, user_profile, NULL, ao2_cleanup);
RAII_VAR(struct bridge_profile *, bridge_profile, NULL, ao2_cleanup);
+ RAII_VAR(struct conf_menu *, menu_profile, NULL, ao2_cleanup);
struct confbridge_cfg *cfg = aco_pending_config(&cfg_info);
if (!cfg) {
@@ -1896,6 +2011,17 @@ static int verify_default_profiles(void)
ao2_link(cfg->user_profiles, user_profile);
}
+ menu_profile = ao2_find(cfg->menus, DEFAULT_MENU_PROFILE, OBJ_KEY);
+ if (!menu_profile) {
+ menu_profile = menu_alloc(DEFAULT_MENU_PROFILE);
+ if (!menu_profile) {
+ return -1;
+ }
+ ast_log(AST_LOG_NOTICE, "Adding %s menu to app_confbridge\n", DEFAULT_MENU_PROFILE);
+ aco_set_defaults(&menu_type, DEFAULT_MENU_PROFILE, menu_profile);
+ ao2_link(cfg->menus, menu_profile);
+ }
+
return 0;
}
@@ -1951,6 +2077,7 @@ int conf_load_config(void)
/* Menu options */
aco_option_register(&cfg_info, "type", ACO_EXACT, menu_types, NULL, OPT_NOOP_T, 0, 0);
+ aco_option_register_custom(&cfg_info, "template", ACO_EXACT, menu_types, NULL, menu_template_handler, 0);
aco_option_register_custom(&cfg_info, "^[0-9A-D*#]+$", ACO_REGEX, menu_types, NULL, menu_option_handler, 0);
if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
@@ -1988,11 +2115,7 @@ const struct user_profile *conf_find_user_profile(struct ast_channel *chan, cons
struct func_confbridge_data *b_data = NULL;
RAII_VAR(struct confbridge_cfg *, cfg, ao2_global_obj_ref(cfg_handle), ao2_cleanup);
- if (!cfg) {
- return NULL;
- }
-
- if (chan) {
+ if (chan && ast_strlen_zero(user_profile_name)) {
ast_channel_lock(chan);
datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL);
ast_channel_unlock(chan);
@@ -2005,6 +2128,9 @@ const struct user_profile *conf_find_user_profile(struct ast_channel *chan, cons
}
}
+ if (!cfg) {
+ return NULL;
+ }
if (ast_strlen_zero(user_profile_name)) {
user_profile_name = DEFAULT_USER_PROFILE;
}
@@ -2042,11 +2168,7 @@ const struct bridge_profile *conf_find_bridge_profile(struct ast_channel *chan,
struct func_confbridge_data *b_data = NULL;
RAII_VAR(struct confbridge_cfg *, cfg, ao2_global_obj_ref(cfg_handle), ao2_cleanup);
- if (!cfg) {
- return NULL;
- }
-
- if (chan) {
+ if (chan && ast_strlen_zero(bridge_profile_name)) {
ast_channel_lock(chan);
datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL);
ast_channel_unlock(chan);
@@ -2058,6 +2180,10 @@ const struct bridge_profile *conf_find_bridge_profile(struct ast_channel *chan,
}
}
}
+
+ if (!cfg) {
+ return NULL;
+ }
if (ast_strlen_zero(bridge_profile_name)) {
bridge_profile_name = DEFAULT_BRIDGE_PROFILE;
}
@@ -2083,7 +2209,7 @@ static void menu_hook_destroy(void *hook_pvt)
struct dtmf_menu_hook_pvt *pvt = hook_pvt;
struct conf_menu_action *action = NULL;
- ao2_ref(pvt->menu, -1);
+ ao2_cleanup(pvt->menu);
while ((action = AST_LIST_REMOVE_HEAD(&pvt->menu_entry.actions, action))) {
ast_free(action);
@@ -2098,24 +2224,6 @@ static int menu_hook_callback(struct ast_bridge_channel *bridge_channel, void *h
return conf_handle_dtmf(bridge_channel, pvt->user, &pvt->menu_entry, pvt->menu);
}
-static int copy_menu_entry(struct conf_menu_entry *dst, struct conf_menu_entry *src)
-{
- struct conf_menu_action *menu_action = NULL;
- struct conf_menu_action *new_menu_action = NULL;
-
- memcpy(dst, src, sizeof(*dst));
- AST_LIST_HEAD_INIT_NOLOCK(&dst->actions);
-
- AST_LIST_TRAVERSE(&src->actions, menu_action, action) {
- if (!(new_menu_action = ast_calloc(1, sizeof(*new_menu_action)))) {
- return -1;
- }
- memcpy(new_menu_action, menu_action, sizeof(*new_menu_action));
- AST_LIST_INSERT_HEAD(&dst->actions, new_menu_action, action);
- }
- return 0;
-}
-
void conf_menu_entry_destroy(struct conf_menu_entry *menu_entry)
{
struct conf_menu_action *menu_action = NULL;
@@ -2141,37 +2249,24 @@ int conf_find_menu_entry_by_sequence(const char *dtmf_sequence, struct conf_menu
return 0;
}
-int conf_set_menu_to_user(const char *menu_name, struct confbridge_user *user)
+static int apply_menu_hooks(struct confbridge_user *user, struct conf_menu *menu)
{
- struct conf_menu *menu;
- struct conf_menu_entry *menu_entry = NULL;
- RAII_VAR(struct confbridge_cfg *, cfg, ao2_global_obj_ref(cfg_handle), ao2_cleanup);
+ struct conf_menu_entry *menu_entry;
- if (!cfg) {
- return -1;
- }
-
- if (!(menu = menu_find(cfg->menus, menu_name))) {
- return -1;
- }
- ao2_lock(menu);
+ SCOPED_AO2LOCK(menu_lock, menu);
AST_LIST_TRAVERSE(&menu->entries, menu_entry, entry) {
struct dtmf_menu_hook_pvt *pvt;
if (!(pvt = ast_calloc(1, sizeof(*pvt)))) {
- ao2_unlock(menu);
- ao2_ref(menu, -1);
return -1;
}
+ pvt->user = user;
+ pvt->menu = ao2_bump(menu);
+
if (copy_menu_entry(&pvt->menu_entry, menu_entry)) {
- ast_free(pvt);
- ao2_unlock(menu);
- ao2_ref(menu, -1);
+ menu_hook_destroy(pvt);
return -1;
}
- pvt->user = user;
- ao2_ref(menu, +1);
- pvt->menu = menu;
if (ast_bridge_dtmf_hook(&user->features, pvt->menu_entry.dtmf,
menu_hook_callback, pvt, menu_hook_destroy, 0)) {
@@ -2179,12 +2274,47 @@ int conf_set_menu_to_user(const char *menu_name, struct confbridge_user *user)
}
}
- ao2_unlock(menu);
- ao2_ref(menu, -1);
-
return 0;
}
+int conf_set_menu_to_user(struct ast_channel *chan, struct confbridge_user *user, const char *menu_profile_name)
+{
+ RAII_VAR(struct confbridge_cfg *, cfg, ao2_global_obj_ref(cfg_handle), ao2_cleanup);
+ RAII_VAR(struct conf_menu *, menu, NULL, ao2_cleanup);
+
+ if (chan && ast_strlen_zero(menu_profile_name)) {
+ struct ast_datastore *datastore;
+ struct func_confbridge_data *b_data;
+
+ ast_channel_lock(chan);
+ datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL);
+ ast_channel_unlock(chan);
+ if (datastore) {
+ /* If a menu exists in the CONFBRIDGE function datastore, use it. */
+ b_data = datastore->data;
+ if (b_data->m_usable) {
+ menu = ao2_bump(b_data->menu);
+ return apply_menu_hooks(user, menu);
+ }
+ }
+ }
+
+ /* Otherwise, we need to get whatever menu profile is specified to use (or default). */
+ if (!cfg) {
+ return -1;
+ }
+
+ if (ast_strlen_zero(menu_profile_name)) {
+ menu_profile_name = DEFAULT_MENU_PROFILE;
+ }
+
+ if (!(menu = ao2_find(cfg->menus, menu_profile_name, OBJ_KEY))) {
+ return -1;
+ }
+
+ return apply_menu_hooks(user, menu);
+}
+
void conf_destroy_config(void)
{
ast_cli_unregister_multiple(cli_confbridge_parser, ARRAY_LEN(cli_confbridge_parser));
diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h
index 71ae5f7de..492cf8557 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -37,6 +37,7 @@
#define DEFAULT_USER_PROFILE "default_user"
#define DEFAULT_BRIDGE_PROFILE "default_bridge"
+#define DEFAULT_MENU_PROFILE "default_menu"
#define DEFAULT_TALKING_THRESHOLD 160
#define DEFAULT_SILENCE_THRESHOLD 2500
@@ -260,32 +261,57 @@ void conf_destroy_config(void);
* \brief find a user profile given a user profile's name and store
* that profile in result structure.
*
- * \details This function first attempts to find any custom user
- * profile that might exist on a channel datastore, if that doesn't
- * exist it looks up the provided user profile name, if that doesn't
- * exist either the default_user profile is used.
-
+ * \param chan channel the user profile is requested for
+ * \param user_profile_name name of the profile requested (optional)
+ * \param result data contained by the user profile will be copied to this struct pointer
+ *
+ * \details If user_profile_name is not provided, this function will
+ * check for the presence of a user profile set by the CONFBRIDGE
+ * function on a channel datastore. If that doesn't exist, the
+ * default_user profile is used.
+ *
* \retval user profile on success
* \retval NULL on failure
*/
const struct user_profile *conf_find_user_profile(struct ast_channel *chan, const char *user_profile_name, struct user_profile *result);
/*!
- * \brief Find a bridge profile
+ * \brief Find a bridge profile given a bridge profile's name and store
+ * that profile in result structure.
*
- * \details Any bridge profile found using this function must be
- * destroyed using conf_bridge_profile_destroy. This function first
- * attempts to find any custom bridge profile that might exist on
- * a channel datastore, if that doesn't exist it looks up the
- * provided bridge profile name, if that doesn't exist either
- * the default_bridge profile is used.
+ * \param chan channel the bridge profile is requested for
+ * \param bridge_profile_name name of the profile requested (optional)
+ * \param result data contained by the bridge profile will be copied to this struct pointer
*
- * \retval Bridge profile on success
+ * \details If bridge_profile_name is not provided, this function will
+ * check for the presence of a bridge profile set by the CONFBRIDGE
+ * function on a channel datastore. If that doesn't exist, the
+ * default_bridge profile is used.
+ *
+ * \retval bridge profile on success
* \retval NULL on failure
*/
const struct bridge_profile *conf_find_bridge_profile(struct ast_channel *chan, const char *bridge_profile_name, struct bridge_profile *result);
/*!
+ * \brief find a menu profile given a menu profile's name and apply
+ * the menu in DTMF hooks.
+ *
+ * \param chan channel the menu profile is requested for
+ * \param user user profile the menu is being applied to
+ * \param menu_profile_name name of the profile requested (optional)
+ *
+ * \details If menu_profile_name is not provided, this function will
+ * check for the presence of a menu profile set by the CONFBRIDGE
+ * function on a channel datastore. If that doesn't exist, the
+ * default_menu profile is used.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
+ */
+int conf_set_menu_to_user(struct ast_channel *chan, struct confbridge_user *user, const char *menu_profile_name);
+
+/*!
* \brief Destroy a bridge profile found by 'conf_find_bridge_profile'
*/
void conf_bridge_profile_destroy(struct bridge_profile *b_profile);
@@ -297,14 +323,6 @@ void conf_bridge_profile_destroy(struct bridge_profile *b_profile);
void conf_bridge_profile_copy(struct bridge_profile *dst, struct bridge_profile *src);
/*!
- * \brief Set a DTMF menu to a conference user by menu name.
- *
- * \retval 0 on success, menu was found and set
- * \retval -1 on error, menu was not found
- */
-int conf_set_menu_to_user(const char *menu_name, struct confbridge_user *user);
-
-/*!
* \brief Finds a menu_entry in a menu structure matched by DTMF sequence.
*
* \note the menu entry found must be destroyed using conf_menu_entry_destroy()