[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