[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