[svn-commits] file: branch file/bridging r107001 - /team/file/bridging/apps/app_confbridge.c
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Sat Mar 8 14:07:08 CST 2008
Author: file
Date: Sat Mar 8 14:07:07 2008
New Revision: 107001
URL: http://svn.digium.com/view/asterisk?view=rev&rev=107001
Log:
Make the user and admin IVRs one and the same, as they share most of the same common options. The admin side now also supports locking/unlocking the conference and ejecting the last joined user.
Modified:
team/file/bridging/apps/app_confbridge.c
Modified: team/file/bridging/apps/app_confbridge.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/apps/app_confbridge.c?view=diff&rev=107001&r1=107000&r2=107001
==============================================================================
--- team/file/bridging/apps/app_confbridge.c (original)
+++ team/file/bridging/apps/app_confbridge.c Sat Mar 8 14:07:07 2008
@@ -74,6 +74,7 @@
struct ast_bridge *bridge; /*!< Bridge structure doing the mixing */
int users; /*!< Number of users present */
unsigned int dynamic:1; /*!< Is this conference bridge dynamically generated? */
+ unsigned int locked:1; /*!< Is this conference bridge locked? */
AST_LIST_HEAD_NOLOCK(, conference_bridge_user) users_list; /*!< List of users participating in the conference bridge */
AST_LIST_ENTRY(conference_bridge) list; /*!< Linked list information */
};
@@ -84,6 +85,7 @@
struct ast_channel *chan; /*!< Asterisk channel participating */
struct ast_flags flags; /*!< Flags passed in when the application was called */
unsigned int muted:1; /*!< Is this user muted or not */
+ unsigned int kicked:1; /*!< User has been kicked from the conference */
AST_LIST_ENTRY(conference_bridge_user) list; /*!< Linked list information */
};
@@ -108,8 +110,18 @@
/* Look for an already existing conference bridge */
AST_LIST_TRAVERSE(&conference_bridges, conference_bridge, list) {
- if (!strcasecmp(conference_bridge->name, name))
+ if (!strcasecmp(conference_bridge->name, name)) {
break;
+ }
+ }
+
+ /* When finding a conference bridge that already exists make sure it is locked or that we are an admin */
+ if (conference_bridge && conference_bridge->locked && !ast_test_flag(&conference_bridge_user->flags, OPTION_ADMIN)) {
+ if (!ast_streamfile(conference_bridge_user->chan, "conf-locked", conference_bridge_user->chan->language)) {
+ ast_waitstream(conference_bridge_user->chan, "");
+ }
+ AST_LIST_UNLOCK(&conference_bridges);
+ return NULL;
}
/* If one was not found try to create one if the dynamic option is set */
@@ -117,6 +129,7 @@
/* Oh dear... the dynamic option was not set or we buggered up and couldn't allocate memory for the darn thing */
if (!dynamic || !(conference_bridge = ast_calloc(1, sizeof(*conference_bridge)))) {
AST_LIST_UNLOCK(&conference_bridges);
+ ast_log(LOG_ERROR, "Conference bridge '%s' does not exist.\n", name);
return NULL;
}
/* Set whether this is dynamic and the name, not having those would be so silly */
@@ -212,19 +225,22 @@
}
/*!
- * \brief DTMF Menu Callback for Administrators
+ * \brief DTMF Menu Callback
*
* \param bridge Bridge this is involving
* \param bridge_channel Bridged channel this is involving
+ * \param hook_pvt User's conference bridge structure
*
* \return Returns 0 on success, -1 on failure
*/
-static int menu_callback_admin(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
-{
- int digit, res = 0;
+static int menu_callback(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
+{
+ struct conference_bridge_user *conference_bridge_user = hook_pvt;
+ struct conference_bridge *conference_bridge = conference_bridge_user->conference_bridge;
+ int digit, res = 0, isadmin = ast_test_flag(&conference_bridge_user->flags, OPTION_ADMIN);
/* Try to play back the user menu, if it fails pass this back up so the bridging core will act on it */
- if (ast_streamfile(bridge_channel->chan, "conf-adminmenu", bridge_channel->chan->language)) {
+ if (ast_streamfile(bridge_channel->chan, (isadmin ? "conf-adminmenu" : "conf-usermenu"), bridge_channel->chan->language)) {
return -1;
}
@@ -232,37 +248,46 @@
digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY);
ast_stopstream(bridge_channel->chan);
- bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
-
- return res;
-}
-
-/*!
- * \brief DTMF Menu Callback for Users
- *
- * \param bridge Bridge this is involving
- * \param bridge_channel Bridged channel this is involving
- *
- * \return Returns 0 on success, -1 on failure
- */
-static int menu_callback_user(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
-{
- int digit, res = 0;
-
- /* Try to play back the user menu, if it fails pass this back up so the bridging core will act on it */
- if (ast_streamfile(bridge_channel->chan, "conf-usermenu", bridge_channel->chan->language)) {
- return -1;
- }
-
- /* Wait for them to enter a digit from the user menu options */
- digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY);
- ast_stopstream(bridge_channel->chan);
-
if (digit == '1') {
/* 1 - Mute or unmute yourself */
- bridge_channel->muted = (!bridge_channel->muted ? 1 : 0);
- if (!(res = ast_streamfile(bridge_channel->chan, (bridge_channel->muted ? "conf-muted" : "conf-unmuted"), bridge_channel->chan->language)))
+ conference_bridge_user->muted = bridge_channel->muted = (!bridge_channel->muted ? 1 : 0);
+ if (!(res = ast_streamfile(bridge_channel->chan, (bridge_channel->muted ? "conf-muted" : "conf-unmuted"), bridge_channel->chan->language))) {
ast_waitstream(bridge_channel->chan, "");
+ }
+ } else if (isadmin && digit == '2') {
+ /* 2 - Unlock or lock conference */
+ conference_bridge->locked = (!conference_bridge->locked ? 1 : 0);
+ if (!(res = ast_streamfile(bridge_channel->chan, (conference_bridge->locked ? "conf-lockednow" : "conf-unlockednow"), bridge_channel->chan->language))) {
+ ast_waitstream(bridge_channel->chan, "");
+ }
+ } else if (isadmin && digit == '3') {
+ /* 3 - Eject last user */
+ struct conference_bridge_user *last_participant = NULL;
+
+ AST_LIST_LOCK(&conference_bridges);
+ if (((last_participant = AST_LIST_LAST(&conference_bridge->users_list)) == conference_bridge_user) || (ast_test_flag(&last_participant->flags, OPTION_ADMIN))) {
+ AST_LIST_UNLOCK(&conference_bridges);
+ if (!(res = ast_streamfile(bridge_channel->chan, "conf-errormenu", bridge_channel->chan->language))) {
+ ast_waitstream(bridge_channel->chan, "");
+ }
+ } else {
+ last_participant->kicked = 1;
+ ast_bridge_remove(conference_bridge->bridge, last_participant->chan);
+ AST_LIST_UNLOCK(&conference_bridges);
+ }
+ } else if (digit == '4') {
+ /* 4 - Decrease listening volume */
+ } else if (digit == '6') {
+ /* 6 - Increase listening volume */
+ } else if (digit == '7') {
+ /* 7 - Decrease talking volume */
+ } else if (digit == '9') {
+ /* 9 - Increase talking volume */
+ } else {
+ /* No valid option was selected */
+ if (!(res = ast_streamfile(bridge_channel->chan, "conf-errormenu", bridge_channel->chan->language))) {
+ ast_waitstream(bridge_channel->chan, "");
+ }
}
bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
@@ -304,21 +329,17 @@
/* Look for a conference bridge matching the provided name */
if (!(conference_bridge = join_conference_bridge(args.conf_name, ast_test_flag(&flags, OPTION_DYNAMIC), &conference_bridge_user))) {
- ast_log(LOG_WARNING, "Conference bridge with name %s does not exist.\n", args.conf_name);
return -1;
}
/* If the menu option is enabled provide a user or admin menu as a custom feature hook */
if (ast_test_flag(&flags, OPTION_MENU)) {
ast_bridge_features_init(&features);
- ast_bridge_features_hook(&features, "#", (ast_test_flag(&flags, OPTION_ADMIN) ? menu_callback_admin : menu_callback_user), &conference_bridge_user);
- }
-
- /* Enter a loop where we basically either play dead air/music on hold, or participant in the conference bridge */
- while (!ast_check_hangup(chan)) {
- /* Join our conference bridge for real */
- ast_bridge_join(conference_bridge->bridge, chan, NULL, &features);
- }
+ ast_bridge_features_hook(&features, "#", menu_callback, &conference_bridge_user);
+ }
+
+ /* Join our conference bridge for real */
+ ast_bridge_join(conference_bridge->bridge, chan, NULL, &features);
/* Easy as pie, depart this channel from the conference bridge */
leave_conference_bridge(conference_bridge, &conference_bridge_user);
@@ -328,6 +349,13 @@
ast_bridge_features_cleanup(&features);
}
+ /* If the user was kicked from the conference play back the audio prompt for it */
+ if (conference_bridge_user.kicked) {
+ if (!(res = ast_streamfile(chan, "conf-kicked", chan->language))) {
+ ast_waitstream(chan, "");
+ }
+ }
+
return res;
}
More information about the svn-commits
mailing list