[asterisk-commits] dvossel: branch dvossel/hd_confbridge r311467 - in /team/dvossel/hd_confbridg...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Mar 21 09:11:59 CDT 2011
Author: dvossel
Date: Mon Mar 21 09:11:51 2011
New Revision: 311467
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=311467
Log:
Adds the ability for every sound in confbridge to be customized.
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=311467&r1=311466&r2=311467
==============================================================================
--- team/dvossel/hd_confbridge/apps/app_confbridge.c (original)
+++ team/dvossel/hd_confbridge/apps/app_confbridge.c Mon Mar 21 09:11:51 2011
@@ -121,6 +121,51 @@
return (!strcasecmp(conference_bridge0->name, conference_bridge1->name) ? CMP_MATCH | CMP_STOP : 0);
}
+/*! \brief Looks to see if sound file is stored in bridge profile sounds, if not
+ * default sound is provided.*/
+static const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds)
+{
+ switch (sound) {
+ case CONF_SOUND_HAS_JOINED:
+ return S_OR(custom_sounds->hasjoin, "conf-hasjoin");
+ case CONF_SOUND_HAS_LEFT:
+ return S_OR(custom_sounds->hasleft, "conf-hasleft");
+ case CONF_SOUND_KICKED:
+ return S_OR(custom_sounds->kicked, "conf-kicked");
+ case CONF_SOUND_MUTED:
+ return S_OR(custom_sounds->muted, "conf-muted");
+ case CONF_SOUND_UNMUTED:
+ return S_OR(custom_sounds->unmuted, "conf-unmuted");
+ case CONF_SOUND_ONLY_ONE:
+ return S_OR(custom_sounds->onlyone, "conf-onlyone");
+ case CONF_SOUND_THERE_ARE:
+ return S_OR(custom_sounds->thereare, "conf-thereare");
+ case CONF_SOUND_OTHER_IN_PARTY:
+ return S_OR(custom_sounds->otherinparty, "conf-otherinparty");
+ case CONF_SOUND_PLACE_IN_CONF:
+ return S_OR(custom_sounds->placeintoconf, "conf-placeintoconf");
+ case CONF_SOUND_WAIT_FOR_LEADER:
+ return S_OR(custom_sounds->waitforleader, "conf-waitforleader");
+ case CONF_SOUND_LEADER_HAS_LEFT:
+ return S_OR(custom_sounds->leaderhasleft, "conf-leaderhasleft");
+ case CONF_SOUND_GET_PIN:
+ return S_OR(custom_sounds->getpin, "conf-getpin");
+ case CONF_SOUND_INVALID_PIN:
+ return S_OR(custom_sounds->invalidpin, "conf-invalidpin");
+ case CONF_SOUND_ONLY_PERSON:
+ return S_OR(custom_sounds->onlyperson, "conf-onlyperson");
+ case CONF_SOUND_LOCKED:
+ return S_OR(custom_sounds->locked, "conf-locked");
+ case CONF_SOUND_LOCKED_NOW:
+ return S_OR(custom_sounds->lockednow, "conf-lockednow");
+ case CONF_SOUND_UNLOCKED_NOW:
+ return S_OR(custom_sounds->unlockednow, "conf-unlockednow");
+ case CONF_SOUND_ERROR_MENU:
+ return S_OR(custom_sounds->errormenu, "conf-errormenu");
+ }
+ return "";
+}
+
static struct ast_frame *rec_read(struct ast_channel *ast)
{
return &ast_null_frame;
@@ -281,18 +326,24 @@
return;
} else if (conference_bridge->users == 2) {
/* Eep, there is one other person */
- if (ast_stream_and_wait(conference_bridge_user->chan, "conf-onlyone", "")) {
+ if (ast_stream_and_wait(conference_bridge_user->chan,
+ conf_get_sound(CONF_SOUND_ONLY_ONE, conference_bridge_user->b_profile.sounds),
+ "")) {
return;
}
} else {
/* Alas multiple others in here */
- if (ast_stream_and_wait(conference_bridge_user->chan, "conf-thereare", "")) {
+ if (ast_stream_and_wait(conference_bridge_user->chan,
+ conf_get_sound(CONF_SOUND_THERE_ARE, conference_bridge_user->b_profile.sounds),
+ "")) {
return;
}
if (ast_say_number(conference_bridge_user->chan, conference_bridge->users - 1, "", conference_bridge_user->chan->language, NULL)) {
return;
}
- if (ast_stream_and_wait(conference_bridge_user->chan, "conf-otherinparty", "")) {
+ if (ast_stream_and_wait(conference_bridge_user->chan,
+ conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, conference_bridge_user->b_profile.sounds),
+ "")) {
return;
}
}
@@ -349,7 +400,8 @@
if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) {
ao2_unlock(conference_bridge);
ast_autoservice_start(conference_bridge_user->chan);
- play_sound_file(conference_bridge, "conf-placeintoconf");
+ play_sound_file(conference_bridge,
+ conf_get_sound(CONF_SOUND_PLACE_IN_CONF, conference_bridge_user->b_profile.sounds));
ast_autoservice_stop(conference_bridge_user->chan);
ao2_lock(conference_bridge);
}
@@ -371,7 +423,9 @@
conference_bridge_user->features.mute = 1;
/* If we have not been quieted play back that they are waiting for the leader */
if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) {
- play_prompt_to_channel(conference_bridge, conference_bridge_user->chan, "conf-waitforleader");
+ play_prompt_to_channel(conference_bridge,
+ conference_bridge_user->chan,
+ conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, conference_bridge_user->b_profile.sounds));
}
/* Start music on hold if needed */
/* We need to recheck the markedusers value here. play_prompt_to_channel unlocks the conference bridge, potentially
@@ -397,7 +451,9 @@
if (conference_bridge->users == 1) {
/* If audio prompts have not been quieted or this prompt quieted play it on out */
if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET | USER_OPT_NOONLYPERSON)) {
- play_prompt_to_channel(conference_bridge, conference_bridge_user->chan, "conf-onlyperson");
+ play_prompt_to_channel(conference_bridge,
+ conference_bridge_user->chan,
+ conf_get_sound(CONF_SOUND_ONLY_PERSON, conference_bridge_user->b_profile.sounds));
}
/* If we need to start music on hold on the channel do so now */
/* We need to re-check the number of users in the conference bridge here because another conference bridge
@@ -455,6 +511,7 @@
ast_bridge_destroy(conference_bridge->bridge);
conference_bridge->bridge = NULL;
}
+ conf_bridge_profile_destroy(&conference_bridge->b_profile);
}
/*!
@@ -501,7 +558,9 @@
ao2_unlock(conference_bridges);
ao2_ref(conference_bridge, -1);
ast_debug(1, "Conference bridge '%s' is locked and caller is not an admin\n", name);
- ast_stream_and_wait(conference_bridge_user->chan, "conf-locked", "");
+ ast_stream_and_wait(conference_bridge_user->chan,
+ conf_get_sound(CONF_SOUND_LOCKED, conference_bridge_user->b_profile.sounds),
+ "");
return NULL;
}
@@ -517,7 +576,7 @@
/* Setup conference bridge parameters */
conference_bridge->record_thread = AST_PTHREADT_NULL;
ast_copy_string(conference_bridge->name, name, sizeof(conference_bridge->name));
- memcpy(&conference_bridge->b_profile, &conference_bridge_user->b_profile, sizeof(conference_bridge->b_profile));
+ conf_bridge_profile_copy(&conference_bridge->b_profile, &conference_bridge_user->b_profile);
/* Create an actual bridge that will do the audio mixing */
if (!(conference_bridge->bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_MULTIMIX, 0))) {
@@ -618,7 +677,8 @@
if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) {
ao2_unlock(conference_bridge);
ast_autoservice_start(conference_bridge_user->chan);
- play_sound_file(conference_bridge, "conf-leaderhasleft");
+ play_sound_file(conference_bridge,
+ conf_get_sound(CONF_SOUND_LEADER_HAS_LEFT, conference_bridge_user->b_profile.sounds));
ast_autoservice_stop(conference_bridge_user->chan);
ao2_lock(conference_bridge);
}
@@ -744,21 +804,26 @@
bridge_channel->chan->name, bridge_channel->chan->uniqueid, conf_name, talking ? "on" : "off");
}
-static int conf_get_pin(struct ast_channel *chan, const char *pin)
+static int conf_get_pin(struct ast_channel *chan, struct conference_bridge_user *conference_bridge_user)
{
char pin_guess[MAX_PIN] = { 0, };
+ const char *pin = conference_bridge_user->u_profile.pin;
char *tmp = pin_guess;
int i, res;
unsigned int len = MAX_PIN - 1;
/* give them three tries to get the pin right */
for (i = 0; i < 3; i++) {
- if (ast_app_getdata(chan, "conf-getpin", tmp, len, 0) >= 0) {
+ if (ast_app_getdata(chan,
+ conf_get_sound(CONF_SOUND_GET_PIN, conference_bridge_user->b_profile.sounds),
+ tmp, len, 0) >= 0) {
if (!strcasecmp(pin, pin_guess)) {
return 0;
}
}
- ast_streamfile(chan, "conf-invalidpin", chan->language);
+ ast_streamfile(chan,
+ conf_get_sound(CONF_SOUND_INVALID_PIN, conference_bridge_user->b_profile.sounds),
+ chan->language);
res = ast_waitstream(chan, AST_DIGIT_ANY);
if (res > 0) {
pin_guess[0] = res;
@@ -857,7 +922,7 @@
/* ask for a PIN immediately after finding user profile. This has to be
* prompted for requardless of quiet setting. */
if (!ast_strlen_zero(conference_bridge_user.u_profile.pin)) {
- if (conf_get_pin(chan, conference_bridge_user.u_profile.pin)) {
+ if (conf_get_pin(chan, &conference_bridge_user)) {
res = -1; /* invalid PIN */
goto confbridge_cleanup;
}
@@ -939,7 +1004,8 @@
if (!ast_strlen_zero(conference_bridge_user.name_rec_location)) {
ast_autoservice_start(chan);
play_sound_file(conference_bridge, conference_bridge_user.name_rec_location);
- play_sound_file(conference_bridge, "conf-hasjoin");
+ play_sound_file(conference_bridge,
+ conf_get_sound(CONF_SOUND_HAS_JOINED, conference_bridge_user.b_profile.sounds));
ast_autoservice_stop(chan);
}
@@ -961,7 +1027,8 @@
if (!quiet && !ast_strlen_zero(conference_bridge_user.name_rec_location)) {
ast_autoservice_start(chan);
play_sound_file(conference_bridge, conference_bridge_user.name_rec_location);
- play_sound_file(conference_bridge, "conf-hasleft");
+ play_sound_file(conference_bridge,
+ conf_get_sound(CONF_SOUND_HAS_LEFT, conference_bridge_user.b_profile.sounds));
ast_autoservice_stop(chan);
}
@@ -981,7 +1048,9 @@
/* If the user was kicked from the conference play back the audio prompt for it */
if (!quiet && conference_bridge_user.kicked) {
- res = ast_stream_and_wait(chan, "conf-kicked", "");
+ res = ast_stream_and_wait(chan,
+ conf_get_sound(CONF_SOUND_KICKED, conference_bridge_user.b_profile.sounds),
+ "");
}
/* Restore volume adjustments to previous values in case they were changed */
@@ -998,7 +1067,7 @@
confbridge_cleanup:
ast_bridge_features_cleanup(&conference_bridge_user.features);
-
+ conf_bridge_profile_destroy(&conference_bridge_user.b_profile);
return res;
}
@@ -1010,7 +1079,10 @@
if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_WAITMARKED) || conference_bridge->markedusers) {
conference_bridge_user->features.mute = (!conference_bridge_user->features.mute ? 1 : 0);
}
- return ast_stream_and_wait(bridge_channel->chan, (conference_bridge_user->features.mute ? "conf-muted" : "conf-unmuted"), "");
+ return ast_stream_and_wait(bridge_channel->chan, (conference_bridge_user->features.mute ?
+ conf_get_sound(CONF_SOUND_MUTED, conference_bridge_user->b_profile.sounds) :
+ conf_get_sound(CONF_SOUND_UNMUTED, conference_bridge_user->b_profile.sounds)),
+ "");
}
static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
@@ -1176,7 +1248,11 @@
}
conference_bridge->locked = (!conference_bridge->locked ? 1 : 0);
res |= ast_stream_and_wait(bridge_channel->chan,
- (conference_bridge->locked ? "conf-lockednow" : "conf-unlockednow"), "");
+ (conference_bridge->locked ?
+ conf_get_sound(CONF_SOUND_LOCKED_NOW, conference_bridge_user->b_profile.sounds) :
+ conf_get_sound(CONF_SOUND_UNLOCKED_NOW, conference_bridge_user->b_profile.sounds)),
+ "");
+
break;
case MENU_ACTION_ADMIN_KICK_LAST:
if (!isadmin) {
@@ -1186,7 +1262,10 @@
if (((last_participant = AST_LIST_LAST(&conference_bridge->users_list)) == conference_bridge_user)
|| (ast_test_flag(&last_participant->u_profile, USER_OPT_ADMIN))) {
ao2_unlock(conference_bridge);
- res = ast_stream_and_wait(bridge_channel->chan, "conf-errormenu", "");
+ res = ast_stream_and_wait(bridge_channel->chan,
+ conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds),
+ "");
+
} else if (last_participant) {
last_participant->kicked = 1;
ast_bridge_remove(conference_bridge->bridge, last_participant->chan);
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=311467&r1=311466&r2=311467
==============================================================================
--- team/dvossel/hd_confbridge/apps/confbridge/conf_config_parser.c (original)
+++ team/dvossel/hd_confbridge/apps/confbridge/conf_config_parser.c Mon Mar 21 09:11:51 2011
@@ -32,6 +32,7 @@
#include "asterisk/astobj2.h"
#include "asterisk/cli.h"
#include "asterisk/bridging_features.h"
+#include "asterisk/stringfields.h"
#define CONF_CONFIG "confbridge.conf"
@@ -119,6 +120,43 @@
{
struct user_profile *entry = obj;
return entry->delme ? CMP_MATCH : 0;
+}
+
+/*! Bridge Profile Sounds functions */
+static void bridge_profile_sounds_destroy_cb(void *obj)
+{
+ struct bridge_profile_sounds *sounds = ao2_alloc(sizeof(*sounds), bridge_profile_sounds_destroy_cb);
+ ast_string_field_free_memory(sounds);
+}
+
+static struct bridge_profile_sounds *bridge_profile_sounds_alloc(void)
+{
+ struct bridge_profile_sounds *sounds = ao2_alloc(sizeof(*sounds), bridge_profile_sounds_destroy_cb);
+
+ if (!sounds) {
+ return NULL;
+ }
+ if (ast_string_field_init(sounds, 1024)) {
+ ao2_ref(sounds, -1);
+ return NULL;
+ }
+
+ return sounds;
+}
+
+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")) {
+ ast_string_field_set(sounds, onlyperson, sound_file);
+ } else {
+ return -1;
+ }
+
+ return 0;
}
/*!
@@ -145,17 +183,26 @@
b_profile->internal_sample_rate = 0;
b_profile->flags = 0;
b_profile->max_members = 0;
+ ao2_ref(b_profile->sounds, -1); /* sounds is read only. Once it has been created
+ * it can never be altered. This prevents having to
+ * do any locking after it is built from the config. */
+ if (!(b_profile->sounds = bridge_profile_sounds_alloc())) {
+ ao2_unlock(b_profile);
+ ao2_ref(b_profile, -1);
+ ao2_unlink(bridge_profiles, b_profile);
+ return -1;
+ }
for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
- if (!strcasecmp(var->name, "internal_sample_rate")) {
+ if (!strcasecmp(var->name, "type")) {
+ continue;
+ } else if (!strcasecmp(var->name, "internal_sample_rate")) {
if (!strcasecmp(var->value, "auto")) {
b_profile->internal_sample_rate = 0;
} else if (sscanf(var->value, "%30u", &b_profile->internal_sample_rate) != 1) {
ast_log(LOG_WARNING, "internal_sample_rate '%s' at line %d of %s is not supported.\n",
var->value, var->lineno, CONF_CONFIG);
}
- } else if (!strcasecmp(var->name, "type")) {
- continue;
} else if (!strcasecmp(var->name, "record_conference")) {
b_profile->flags = ast_true(var->value) ?
b_profile->flags | BRIDGE_OPT_RECORD_CONFERENCE :
@@ -163,6 +210,11 @@
} else if (!strcasecmp(var->name, "max_members")) {
if (sscanf(var->value, "%30u", &b_profile->max_members) != 1) {
ast_log(LOG_WARNING, "max_members '%s' at line %d of %s is not supported.\n",
+ var->value, var->lineno, CONF_CONFIG);
+ }
+ } else if (strlen(var->name) >= 5 && !strncasecmp(var->name, "sound", 8)) {
+ if (set_sound(var->name, var->value, b_profile->sounds)) {
+ ast_log(LOG_WARNING, "'%s' at line %d of %s is not supported.\n",
var->value, var->lineno, CONF_CONFIG);
}
} else {
@@ -600,6 +652,7 @@
ast_cli(a->fd,"Internal Sample Rate: %s\n", tmp);
ast_cli(a->fd,"\n");
+ conf_bridge_profile_destroy(&b_profile);
return CLI_SUCCESS;
}
@@ -827,6 +880,22 @@
return result;
}
+void conf_bridge_profile_copy(struct bridge_profile *dst, struct bridge_profile *src)
+{
+ memcpy(dst, src, sizeof(*dst));
+ if (src->sounds) {
+ ao2_ref(src->sounds, +1);
+ }
+}
+
+void conf_bridge_profile_destroy(struct bridge_profile *b_profile)
+{
+ if (b_profile->sounds) {
+ ao2_ref(b_profile->sounds, -1);
+ b_profile->sounds = NULL;
+ }
+}
+
const struct bridge_profile *conf_find_bridge_profile(const char *bridge_profile_name, struct bridge_profile *result)
{
struct bridge_profile tmp;
@@ -837,7 +906,7 @@
return NULL;
}
ao2_lock(tmp2);
- memcpy(result, tmp2, sizeof(*result));
+ conf_bridge_profile_copy(result, tmp2);
ao2_unlock(tmp2);
ao2_ref(tmp2, -1);
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=311467&r1=311466&r2=311467
==============================================================================
--- team/dvossel/hd_confbridge/apps/confbridge/include/confbridge.h (original)
+++ team/dvossel/hd_confbridge/apps/confbridge/include/confbridge.h Mon Mar 21 09:11:51 2011
@@ -111,11 +111,56 @@
int delme;
};
+enum conf_sounds {
+ CONF_SOUND_HAS_JOINED,
+ CONF_SOUND_HAS_LEFT,
+ CONF_SOUND_KICKED,
+ CONF_SOUND_MUTED,
+ CONF_SOUND_UNMUTED,
+ CONF_SOUND_ONLY_ONE,
+ CONF_SOUND_THERE_ARE,
+ CONF_SOUND_OTHER_IN_PARTY,
+ CONF_SOUND_PLACE_IN_CONF,
+ CONF_SOUND_WAIT_FOR_LEADER,
+ CONF_SOUND_LEADER_HAS_LEFT,
+ CONF_SOUND_GET_PIN,
+ CONF_SOUND_INVALID_PIN,
+ CONF_SOUND_ONLY_PERSON,
+ CONF_SOUND_LOCKED,
+ CONF_SOUND_LOCKED_NOW,
+ CONF_SOUND_UNLOCKED_NOW,
+ CONF_SOUND_ERROR_MENU,
+};
+
+struct bridge_profile_sounds {
+ AST_DECLARE_STRING_FIELDS(
+ AST_STRING_FIELD(hasjoin);
+ AST_STRING_FIELD(hasleft);
+ AST_STRING_FIELD(kicked);
+ AST_STRING_FIELD(muted);
+ AST_STRING_FIELD(unmuted);
+ AST_STRING_FIELD(onlyone);
+ AST_STRING_FIELD(thereare);
+ AST_STRING_FIELD(otherinparty);
+ AST_STRING_FIELD(placeintoconf);
+ AST_STRING_FIELD(waitforleader);
+ AST_STRING_FIELD(leaderhasleft);
+ AST_STRING_FIELD(getpin);
+ AST_STRING_FIELD(invalidpin);
+ AST_STRING_FIELD(onlyperson);
+ AST_STRING_FIELD(locked);
+ AST_STRING_FIELD(lockednow);
+ AST_STRING_FIELD(unlockednow);
+ AST_STRING_FIELD(errormenu);
+ );
+};
+
struct bridge_profile {
char name[64];
unsigned int flags;
unsigned int max_members; /*!< The maximum number of participants allowed in the conference */
unsigned int internal_sample_rate; /*!< The internal sample rate of the bridge. 0 when set to auto adjust mode. */
+ struct bridge_profile_sounds *sounds;
int delme;
};
@@ -166,10 +211,24 @@
/*!
* \brief find a bridge profile given a bridge profile's name.
*
+ * \details Any bridge profile found using this function must be
+ * destroyed using conf_bridge_profile_destroy.
+ *
* \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);
+
+/*!
+ * \brief Destroy a bridge profile found by 'conf_find_bridge_profile'
+ */
+void conf_bridge_profile_destroy(struct bridge_profile *b_profile);
+
+/*!
+ * \brief copies a bridge profile
+ * \note conf_bridge_profile_destroy must be called on the dst structure
+ */
+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.
More information about the asterisk-commits
mailing list