[asterisk-commits] dvossel: branch dvossel/hd_confbridge r311489 - in /team/dvossel/hd_confbridg...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Mar 21 14:40:34 CDT 2011
Author: dvossel
Date: Mon Mar 21 14:40:30 2011
New Revision: 311489
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=311489
Log:
Introduction of the CONFBRIDGE dialplan function for dynamic user and bridge profiles.
Modified:
team/dvossel/hd_confbridge/apps/app_confbridge.c
team/dvossel/hd_confbridge/apps/confbridge/conf_config_parser.c
team/dvossel/hd_confbridge/apps/confbridge/include/confbridge.h
Modified: team/dvossel/hd_confbridge/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/apps/app_confbridge.c?view=diff&rev=311489&r1=311488&r2=311489
==============================================================================
--- team/dvossel/hd_confbridge/apps/app_confbridge.c (original)
+++ team/dvossel/hd_confbridge/apps/app_confbridge.c Mon Mar 21 14:40:30 2011
@@ -53,31 +53,52 @@
#include "asterisk/manager.h"
/*** DOCUMENTATION
- <application name="ConfBridge" language="en_US">
- <synopsis>
- Conference bridge application.
- </synopsis>
- <syntax>
- <parameter name="confno">
- <para>The conference number</para>
- </parameter>
- <parameter name="bridge_profile">
- <para>The bridge profile name from confbridge.conf. When left blank, the 'default_bridge' profile found in confbridge.conf will be used if present.</para>
- </parameter>
- <parameter name="user_profile">
- <para>The user profile name from confbridge.conf. When left blank, the 'default_user' profile found in confbridge.conf will be used if present.</para>
- </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>
- </parameter>
- </syntax>
- <description>
- <para>Enters the user into a specified conference bridge. The user can exit the conference by hangup only.</para>
- <para>The join sound can be set using the <literal>CONFBRIDGE_JOIN_SOUND</literal> variable and the leave sound can be set using the <literal>CONFBRIDGE_LEAVE_SOUND</literal> variable. These can be unique to the caller.</para>
- <note><para>This application will not automatically answer the channel.</para></note>
- </description>
- </application>
-***/
+ <application name="ConfBridge" language="en_US">
+ <synopsis>
+ Conference bridge application.
+ </synopsis>
+ <syntax>
+ <parameter name="confno">
+ <para>The conference number</para>
+ </parameter>
+ <parameter name="bridge_profile">
+ <para>The bridge profile name from confbridge.conf. When left blank, the 'default_bridge' profile found in confbridge.conf will be used if present.</para>
+ </parameter>
+ <parameter name="user_profile">
+ <para>The user profile name from confbridge.conf. When left blank, the 'default_user' profile found in confbridge.conf will be used if present.</para>
+ </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>
+ </parameter>
+ </syntax>
+ <description>
+ <para>Enters the user into a specified conference bridge. The user can exit the conference by hangup only.</para>
+ <para>The join sound can be set using the <literal>CONFBRIDGE_JOIN_SOUND</literal> variable and the leave sound can be set using the <literal>CONFBRIDGE_LEAVE_SOUND</literal> variable. These can be unique to the caller.</para>
+ <note><para>This application will not automatically answer the channel.</para></note>
+ </description>
+ </application>
+ <function name="CONFBRIDGE" language="en_US">
+ <synopsis>
+ Set a custom dynamic bridge and user profile on a channel for the ConfBridge application.
+ </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>
+ </parameter>
+ <parameter name="option" required="true">
+ <para>Option refers to confbridge.conf option that is being set dynamically on this channel.</para>
+ </parameter>
+ </syntax>
+ <description>
+ <para>Examples:</para>
+ <para>exten => 1,1,Answer() </para>
+ <para>exten => 1,n,Set(CONFBRIDGE(user,announce_join_leave)=yes) ;Have the user record a name before entering </para>
+ <para>exten => 1,n,Set(CONFBRIDGE(user,startmuted)=yes) ; start the user muted</para>
+ <para>exten => 1,n,ConfBridge(1) ; The custom set user profile on this channel will automatically be used. </para>
+ </description>
+ </function>
+ ***/
+
/*!
* \par Playing back a file to a channel in a conference
@@ -874,8 +895,8 @@
{
int res = 0, volume_adjustments[2];
char *parse;
- const char *b_profile_name = "default_bridge";
- const char *u_profile_name = "default_user";
+ const char *b_profile_name = DEFAULT_BRIDGE_PROFILE;
+ const char *u_profile_name = DEFAULT_USER_PROFILE;
struct conference_bridge *conference_bridge = NULL;
struct conference_bridge_user conference_bridge_user = {
.chan = chan,
@@ -908,13 +929,13 @@
if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) {
b_profile_name = args.b_profile_name;
}
- conf_find_bridge_profile(b_profile_name, &conference_bridge_user.b_profile);
+ conf_find_bridge_profile(chan, b_profile_name, &conference_bridge_user.b_profile);
/* user profile name */
if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) {
u_profile_name = args.u_profile_name;
}
- conf_find_user_profile(u_profile_name, &conference_bridge_user.u_profile);
+ conf_find_user_profile(chan, u_profile_name, &conference_bridge_user.u_profile);
quiet = ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_QUIET);
/* ask for a PIN immediately after finding user profile. This has to be
@@ -1444,12 +1465,18 @@
AST_CLI_DEFINE(handle_cli_confbridge_list, "List conference bridges and participants."),
AST_CLI_DEFINE(handle_cli_confbridge_kick, "Kick participants out of conference bridges."),
};
+static struct ast_custom_function confbridge_function = {
+ .name = "CONFBRIDGE",
+ .write = func_confbridge_helper,
+};
/*! \brief Called when module is being unloaded */
static int unload_module(void)
{
int res = ast_unregister_application(app);
+ ast_custom_function_unregister(&confbridge_function);
+
ast_cli_unregister_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry));
/* Get rid of the conference bridges container. Since we only allow dynamic ones none will be active. */
@@ -1466,6 +1493,10 @@
/*! \brief Called when module is being loaded */
static int load_module(void)
{
+
+ if ((ast_custom_function_register(&confbridge_function))) {
+ return AST_MODULE_LOAD_FAILURE;
+ }
if (!(record_tech.capabilities = ast_format_cap_alloc())) {
return AST_MODULE_LOAD_FAILURE;
}
Modified: team/dvossel/hd_confbridge/apps/confbridge/conf_config_parser.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/apps/confbridge/conf_config_parser.c?view=diff&rev=311489&r1=311488&r2=311489
==============================================================================
--- team/dvossel/hd_confbridge/apps/confbridge/conf_config_parser.c (original)
+++ team/dvossel/hd_confbridge/apps/confbridge/conf_config_parser.c Mon Mar 21 14:40:30 2011
@@ -33,6 +33,7 @@
#include "asterisk/cli.h"
#include "asterisk/bridging_features.h"
#include "asterisk/stringfields.h"
+#include "asterisk/pbx.h"
#define CONF_CONFIG "confbridge.conf"
@@ -144,13 +145,81 @@
return sounds;
}
+static int set_user_option(const char *name, const char *value, struct user_profile *u_profile)
+{
+ if (!strcasecmp(name, "admin")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_ADMIN :
+ u_profile->flags & ~USER_OPT_ADMIN;
+ } else if (!strcasecmp(name, "marked")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_MARKEDUSER :
+ u_profile->flags & ~USER_OPT_MARKEDUSER;
+ } else if (!strcasecmp(name, "startmuted")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_STARTMUTED :
+ u_profile->flags & ~USER_OPT_STARTMUTED;
+ } else if (!strcasecmp(name, "music_on_hold_when_empty")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_MUSICONHOLD :
+ u_profile->flags & ~USER_OPT_MUSICONHOLD;
+ } else if (!strcasecmp(name, "quiet")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_QUIET :
+ u_profile->flags & ~USER_OPT_QUIET;
+ } else if (!strcasecmp(name, "announce_user_count")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_ANNOUNCEUSERCOUNT :
+ u_profile->flags & ~USER_OPT_ANNOUNCEUSERCOUNT;
+ } else if (!strcasecmp(name, "announce_only_user")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags & ~USER_OPT_NOONLYPERSON :
+ u_profile->flags | USER_OPT_NOONLYPERSON;
+ } else if (!strcasecmp(name, "wait_marked")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_WAITMARKED :
+ u_profile->flags & ~USER_OPT_WAITMARKED;
+ } else if (!strcasecmp(name, "end_marked")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_ENDMARKED :
+ u_profile->flags & ~USER_OPT_ENDMARKED;
+ } else if (!strcasecmp(name, "talk_detection_events")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_TALKER_DETECT :
+ u_profile->flags & ~USER_OPT_TALKER_DETECT;
+ } else if (!strcasecmp(name, "dtmf_passthrough")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_DTMF_PASS:
+ u_profile->flags & ~USER_OPT_DTMF_PASS;
+ } else if (!strcasecmp(name, "announce_join_leave")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_ANNOUNCE_JOIN_LEAVE :
+ u_profile->flags & ~USER_OPT_ANNOUNCE_JOIN_LEAVE;
+ } else if (!strcasecmp(name, "pin")) {
+ ast_copy_string(u_profile->pin, value, sizeof(u_profile->pin));
+ } else if (!strcasecmp(name, "music_on_hold_class")) {
+ ast_copy_string(u_profile->moh_class, value, sizeof(u_profile->moh_class));
+ } else if (!strcasecmp(name, "denoise")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_DENOISE :
+ u_profile->flags & ~USER_OPT_DENOISE;
+ } else if (!strcasecmp(name, "drop_silence")) {
+ u_profile->flags = ast_true(value) ?
+ u_profile->flags | USER_OPT_DROP_SILENCE :
+ u_profile->flags & ~USER_OPT_DROP_SILENCE;
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
static int set_sound(const char *sound_name, const char *sound_file, struct bridge_profile_sounds *sounds)
{
if (ast_strlen_zero(sound_file)) {
return -1;
}
- if (!strcasecmp(sound_name, "sound_onlyperson")) {
+ if (!strcasecmp(sound_name, "sound_only_person")) {
ast_string_field_set(sounds, onlyperson, sound_file);
} else if (!strcasecmp(sound_name, "sound_has_joined")) {
ast_string_field_set(sounds, hasjoin, sound_file);
@@ -188,7 +257,6 @@
return 0;
}
-
static int set_bridge_option(const char *name, const char *value, struct bridge_profile *b_profile)
{
if (!strcasecmp(name, "internal_sample_rate")) {
@@ -214,6 +282,92 @@
}
return 0;
+}
+
+/*! CONFBRIDGE dialplan function functions and channel datastore. */
+struct func_confbridge_data {
+ struct bridge_profile b_profile;
+ struct user_profile u_profile;
+ int b_usable:1; /*!< Tells if bridge profile is usable or not */
+ int u_usable:1; /*!< Tells if user profile is usable or not */
+};
+static void func_confbridge_destroy_cb(void *data)
+{
+ struct func_confbridge_data *b_data = data;
+ conf_bridge_profile_destroy(&b_data->b_profile);
+ ast_free(b_data);
+};
+static const struct ast_datastore_info confbridge_datastore = {
+ .type = "confbridge",
+ .destroy = func_confbridge_destroy_cb
+};
+int func_confbridge_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value)
+{
+ struct ast_datastore *datastore = NULL;
+ struct func_confbridge_data *b_data = NULL;
+ char *parse = NULL;
+ int new = 0;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(type);
+ AST_APP_ARG(option);
+ );
+
+ /* parse all the required arguments and make sure they exist. */
+ if (ast_strlen_zero(data) || ast_strlen_zero(value)) {
+ return -1;
+ }
+ parse = ast_strdupa(data);
+ AST_STANDARD_APP_ARGS(args, parse);
+ if (ast_strlen_zero(args.type) || ast_strlen_zero(args.option)) {
+ return -1;
+ }
+
+ ast_channel_lock(chan);
+ if (!(datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL))) {
+ ast_channel_unlock(chan);
+
+ if (!(datastore = ast_datastore_alloc(&confbridge_datastore, NULL))) {
+ return 0;
+ }
+ if (!(b_data = ast_calloc(1, sizeof(*b_data)))) {
+ ast_datastore_free(datastore);
+ return 0;
+ }
+ if (!(b_data->b_profile.sounds = bridge_profile_sounds_alloc())) {
+ ast_datastore_free(datastore);
+ ast_free(b_data);
+ return 0;
+ }
+ datastore->data = b_data;
+ new = 1;
+ } else {
+ ast_channel_unlock(chan);
+ b_data = datastore->data;
+ }
+
+ /* SET(CONFBRIDGE(type,option)=value) */
+ if (!strcasecmp(args.type, "bridge") && !set_bridge_option(args.option, value, &b_data->b_profile)) {
+ b_data->b_usable = 1;
+ } else if (!strcasecmp(args.type, "user") && !set_user_option(args.option, value, &b_data->u_profile)) {
+ b_data->u_usable = 1;
+ } else {
+ ast_log(LOG_WARNING, "Profile type \"%s\" can not be set in CONFBRIDGE function with option \"%s\" and value \"%s\"\n",
+ args.type, args.option, value);
+ goto cleanup_error;
+ }
+ if (new) {
+ ast_channel_lock(chan);
+ ast_channel_datastore_add(chan, datastore);
+ ast_channel_unlock(chan);
+ }
+ return 0;
+
+cleanup_error:
+ ast_log(LOG_ERROR, "Invalid argument provided to the %s function\n", cmd);
+ if (new) {
+ ast_datastore_free(datastore);
+ }
+ return -1;
}
/*!
@@ -261,74 +415,6 @@
ao2_unlock(b_profile);
ao2_ref(b_profile, -1);
- return 0;
-}
-
-static int set_user_option(const char *name, const char *value, struct user_profile *u_profile)
-{
- if (!strcasecmp(name, "admin")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_ADMIN :
- u_profile->flags & ~USER_OPT_ADMIN;
- } else if (!strcasecmp(name, "marked")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_MARKEDUSER :
- u_profile->flags & ~USER_OPT_MARKEDUSER;
- } else if (!strcasecmp(name, "startmuted")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_STARTMUTED :
- u_profile->flags & ~USER_OPT_STARTMUTED;
- } else if (!strcasecmp(name, "music_on_hold_when_empty")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_MUSICONHOLD :
- u_profile->flags & ~USER_OPT_MUSICONHOLD;
- } else if (!strcasecmp(name, "quiet")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_QUIET :
- u_profile->flags & ~USER_OPT_QUIET;
- } else if (!strcasecmp(name, "announce_user_count")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_ANNOUNCEUSERCOUNT :
- u_profile->flags & ~USER_OPT_ANNOUNCEUSERCOUNT;
- } else if (!strcasecmp(name, "announce_only_user")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags & ~USER_OPT_NOONLYPERSON :
- u_profile->flags | USER_OPT_NOONLYPERSON;
- } else if (!strcasecmp(name, "wait_marked")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_WAITMARKED :
- u_profile->flags & ~USER_OPT_WAITMARKED;
- } else if (!strcasecmp(name, "end_marked")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_ENDMARKED :
- u_profile->flags & ~USER_OPT_ENDMARKED;
- } else if (!strcasecmp(name, "talk_detection_events")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_TALKER_DETECT :
- u_profile->flags & ~USER_OPT_TALKER_DETECT;
- } else if (!strcasecmp(name, "dtmf_passthrough")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_DTMF_PASS:
- u_profile->flags & ~USER_OPT_DTMF_PASS;
- } else if (!strcasecmp(name, "announce_join_leave")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_ANNOUNCE_JOIN_LEAVE :
- u_profile->flags & ~USER_OPT_ANNOUNCE_JOIN_LEAVE;
- } else if (!strcasecmp(name, "pin")) {
- ast_copy_string(u_profile->pin, value, sizeof(u_profile->pin));
- } else if (!strcasecmp(name, "music_on_hold_class")) {
- ast_copy_string(u_profile->moh_class, value, sizeof(u_profile->moh_class));
- } else if (!strcasecmp(name, "denoise")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_DENOISE :
- u_profile->flags & ~USER_OPT_DENOISE;
- } else if (!strcasecmp(name, "drop_silence")) {
- u_profile->flags = ast_true(value) ?
- u_profile->flags | USER_OPT_DROP_SILENCE :
- u_profile->flags & ~USER_OPT_DROP_SILENCE;
- } else {
- return -1;
- }
return 0;
}
@@ -599,7 +685,7 @@
return CLI_SHOWUSAGE;
}
- if (!(conf_find_user_profile(a->argv[4], &u_profile))) {
+ if (!(conf_find_user_profile(NULL, a->argv[4], &u_profile))) {
ast_cli(a->fd, "No conference user profile named '%s' found!\n", a->argv[4]);
return CLI_SUCCESS;
}
@@ -730,7 +816,7 @@
return CLI_SHOWUSAGE;
}
- if (!(conf_find_bridge_profile(a->argv[4], &b_profile))) {
+ if (!(conf_find_bridge_profile(NULL, a->argv[4], &b_profile))) {
ast_cli(a->fd, "No conference bridge profile named '%s' found!\n", a->argv[4]);
return CLI_SUCCESS;
}
@@ -1013,12 +1099,28 @@
return 0;
}
-const struct user_profile *conf_find_user_profile(const char *user_profile_name, struct user_profile *result)
+const struct user_profile *conf_find_user_profile(struct ast_channel *chan, const char *user_profile_name, struct user_profile *result)
{
struct user_profile tmp;
struct user_profile *tmp2;
+ struct ast_datastore *datastore = NULL;
+ struct func_confbridge_data *b_data = NULL;
ast_copy_string(tmp.name, user_profile_name, sizeof(tmp.name));
+ ast_channel_lock(chan);
+ if ((datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL))) {
+ ast_channel_unlock(chan);
+ b_data = datastore->data;
+ if (b_data->u_usable) {
+ memcpy(result, &b_data->u_profile, sizeof(*result));
+ return result;
+ }
+ }
+ ast_channel_unlock(chan);
+
+ if (ast_strlen_zero(user_profile_name)) {
+ user_profile_name = DEFAULT_USER_PROFILE;
+ }
if (!(tmp2 = ao2_find(user_profiles, &tmp, OBJ_POINTER))) {
return NULL;
}
@@ -1046,12 +1148,28 @@
}
}
-const struct bridge_profile *conf_find_bridge_profile(const char *bridge_profile_name, struct bridge_profile *result)
+const struct bridge_profile *conf_find_bridge_profile(struct ast_channel *chan, const char *bridge_profile_name, struct bridge_profile *result)
{
struct bridge_profile tmp;
struct bridge_profile *tmp2;
+ struct ast_datastore *datastore = NULL;
+ struct func_confbridge_data *b_data = NULL;
ast_copy_string(tmp.name, bridge_profile_name, sizeof(tmp.name));
+ ast_channel_lock(chan);
+ if ((datastore = ast_channel_datastore_find(chan, &confbridge_datastore, NULL))) {
+ ast_channel_unlock(chan);
+ b_data = datastore->data;
+ if (b_data->b_usable) {
+ conf_bridge_profile_copy(result, &b_data->b_profile);
+ return result;
+ }
+ }
+ ast_channel_unlock(chan);
+
+ if (ast_strlen_zero(bridge_profile_name)) {
+ bridge_profile_name = DEFAULT_BRIDGE_PROFILE;
+ }
if (!(tmp2 = ao2_find(bridge_profiles, &tmp, OBJ_POINTER))) {
return NULL;
}
Modified: team/dvossel/hd_confbridge/apps/confbridge/include/confbridge.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/apps/confbridge/include/confbridge.h?view=diff&rev=311489&r1=311488&r2=311489
==============================================================================
--- team/dvossel/hd_confbridge/apps/confbridge/include/confbridge.h (original)
+++ team/dvossel/hd_confbridge/apps/confbridge/include/confbridge.h Mon Mar 21 14:40:30 2011
@@ -30,6 +30,9 @@
#define MAX_CONF_NAME 32
/* Maximum length of a conference pin */
#define MAX_PIN 80
+
+#define DEFAULT_USER_PROFILE "default_user"
+#define DEFAULT_BRIDGE_PROFILE "default_bridge"
enum user_profile_flags {
USER_OPT_ADMIN = (1 << 0), /*!< Set if the caller is an administrator */
@@ -203,21 +206,30 @@
* \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.
+
* \retval user profile on success
* \retval NULL on failure
*/
-const struct user_profile *conf_find_user_profile(const char *user_profile_name, struct user_profile *result);
-
-/*!
- * \brief find a bridge profile given a bridge profile's name.
+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
*
* \details Any bridge profile found using this function must be
- * destroyed using conf_bridge_profile_destroy.
+ * 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.
*
* \retval Bridge profile on success
* \retval NULL on failure
*/
-const struct bridge_profile *conf_find_bridge_profile(const char *bridge_profile_name, struct bridge_profile *result);
+const struct bridge_profile *conf_find_bridge_profile(struct ast_channel *chan, const char *bridge_profile_name, struct bridge_profile *result);
/*!
* \brief Destroy a bridge profile found by 'conf_find_bridge_profile'
@@ -281,4 +293,6 @@
/*! \brief Looks to see if sound file is stored in bridge profile sounds, if not
* default sound is provided.*/
const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds);
+
+int func_confbridge_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value);
#endif
More information about the asterisk-commits
mailing list