[svn-commits] file: branch file/bridging r110471 - /team/file/bridging/apps/app_confbridge.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Mar 20 22:11:03 CDT 2008


Author: file
Date: Thu Mar 20 22:11:02 2008
New Revision: 110471

URL: http://svn.digium.com/view/asterisk?view=rev&rev=110471
Log:
Add preliminary code for marked user based conferences.

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=110471&r1=110470&r2=110471
==============================================================================
--- team/file/bridging/apps/app_confbridge.c (original)
+++ team/file/bridging/apps/app_confbridge.c Thu Mar 20 22:11:02 2008
@@ -130,6 +130,8 @@
 /*! \brief List of conference bridges configured or currently in existence */
 static AST_LIST_HEAD_STATIC(conference_bridges, conference_bridge);
 
+static int play_sound_file(struct conference_bridge *conference_bridge, const char *filename);
+
 /*!
  * \brief Announce number of users in the conference bridge to the caller
  *
@@ -165,6 +167,118 @@
 }
 
 /*!
+ * \brief Perform post-joining marked specific actions
+ *
+ * \param conference_bridge Conference bridge being joined
+ * \param conference_bridge_user Conference bridge user joining
+ *
+ * \return Nothing
+ */
+static void post_join_marked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
+{
+	if (ast_test_flag(&conference_bridge_user->flags, OPTION_MARKEDUSER)) {
+		struct conference_bridge_user *other_conference_bridge_user = NULL;
+
+		/* If we are not the first marked user to join just bail out now */
+		if (conference_bridge->markedusers >= 2) {
+			return;
+		}
+
+		/* Iterate through every participant stopping MOH on them if need be */
+		AST_LIST_TRAVERSE(&conference_bridge->users_list, other_conference_bridge_user, list) {
+			if (other_conference_bridge_user == conference_bridge_user) {
+				continue;
+			}
+			if (ast_test_flag(&other_conference_bridge_user->flags, OPTION_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other_conference_bridge_user->chan)) {
+				ast_moh_stop(other_conference_bridge_user->chan);
+				ast_bridge_unsuspend(conference_bridge->bridge, other_conference_bridge_user->chan);
+			}
+		}
+
+		/* Next play the audio file stating they are going to placed into the conference */
+		AST_LIST_UNLOCK(&conference_bridges);
+		ast_autoservice_start(conference_bridge_user->chan);
+		play_sound_file(conference_bridge, "conf-placeintoconf");
+		ast_autoservice_stop(conference_bridge_user->chan);
+		AST_LIST_LOCK(&conference_bridges);
+
+		/* Finally iterate through and unmute them all */
+		AST_LIST_TRAVERSE(&conference_bridge->users_list, other_conference_bridge_user, list) {
+			if (other_conference_bridge_user == conference_bridge_user) {
+				continue;
+			}
+			other_conference_bridge_user->features.mute = 0;
+		}
+
+	} else {
+		/* If a marked user already exists in the conference bridge we can just bail out now */
+		if (conference_bridge->markedusers) {
+			return;
+		}
+		/* Be sure we are muted so we can't talk to anybody else waiting */
+		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->flags, OPTION_QUIET)) {
+			AST_LIST_UNLOCK(&conference_bridges);
+			ast_stream_and_wait(conference_bridge_user->chan, "conf-waitforleader", "");
+			AST_LIST_LOCK(&conference_bridges);
+		}
+		/* Start music on hold if needed */
+		if (ast_test_flag(&conference_bridge_user->flags, OPTION_MUSICONHOLD)) {
+			ast_moh_start(conference_bridge_user->chan, conference_bridge_user->opt_args[OPTION_MUSICONHOLD_CLASS], NULL);
+		}
+	}
+
+	return;
+}
+
+/*!
+ * \brief Perform post-joining non-marked specific actions
+ *
+ * \param conference_bridge Conference bridge being joined
+ * \param conference_bridge_user Conference bridge user joining
+ *
+ * \return Nothing
+ */
+static void post_join_unmarked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
+{
+	/* Play back audio prompt and start MOH if need be if we are the first participant */
+	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->flags, OPTION_QUIET) && !ast_test_flag(&conference_bridge_user->flags, OPTION_NOONLYPERSON)) {
+			AST_LIST_UNLOCK(&conference_bridges);
+			ast_stream_and_wait(conference_bridge_user->chan, "conf-onlyperson", "");
+			AST_LIST_LOCK(&conference_bridges);
+		}
+		/* If we need to start music on hold on the channel do so now */
+		if (ast_test_flag(&conference_bridge_user->flags, OPTION_MUSICONHOLD)) {
+			ast_moh_start(conference_bridge_user->chan, conference_bridge_user->opt_args[OPTION_MUSICONHOLD_CLASS], NULL);
+		}
+		return;
+	}
+
+	/* Announce number of users if need be */
+	if (ast_test_flag(&conference_bridge_user->flags, OPTION_ANNOUNCEUSERCOUNT)) {
+		AST_LIST_UNLOCK(&conference_bridges);
+		announce_user_count(conference_bridge, conference_bridge_user);
+		AST_LIST_LOCK(&conference_bridges);
+	}
+
+	/* If we are the second participant we may need to stop music on hold on the first */
+	if (conference_bridge->users == 2) {
+		struct conference_bridge_user *first_participant = AST_LIST_FIRST(&conference_bridge->users_list);
+
+		/* Temporarily suspend the above participant from the bridge so we have control to stop MOH if needed */
+		if (ast_test_flag(&first_participant->flags, OPTION_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
+			ast_moh_stop(first_participant->chan);
+			ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
+		}
+	}
+
+	return;
+}
+
+/*!
  * \brief Join a conference bridge
  *
  * \param name The conference name
@@ -175,7 +289,6 @@
 static struct conference_bridge *join_conference_bridge(const char *name, struct conference_bridge_user *conference_bridge_user)
 {
 	struct conference_bridge *conference_bridge = NULL;
-	int previous_participants = 0;
 
 	AST_LIST_LOCK(&conference_bridges);
 
@@ -223,47 +336,18 @@
 	AST_LIST_INSERT_TAIL(&conference_bridge->users_list, conference_bridge_user, list);
 
 	/* Increment the users count on the bridge, but record it as it is going to need to be known right after this */
-	previous_participants = ast_atomic_fetchadd_int(&conference_bridge->users, +1);
+	ast_atomic_fetchadd_int(&conference_bridge->users, +1);
 
 	/* If the caller is a marked user bump up the count */
 	if (ast_test_flag(&conference_bridge_user->flags, OPTION_MARKEDUSER)) {
 		ast_atomic_fetchadd_int(&conference_bridge->markedusers, +1);
 	}
 
-	/* If we are the first participant we may need to start MOH, if we are the second participant we may need to stop MOH on the first */
-	if (previous_participants == 0) {
-		if (!ast_test_flag(&conference_bridge_user->flags, OPTION_QUIET) && !ast_test_flag(&conference_bridge_user->flags, OPTION_NOONLYPERSON)) {
-			/* Play back the "you are currently the only person in this conference" recording while not blocking, as that would be silly. */
-			AST_LIST_UNLOCK(&conference_bridges);
-			ast_stream_and_wait(conference_bridge_user->chan, "conf-onlyperson", "");
-			AST_LIST_LOCK(&conference_bridges);
-		}
-		/* We have to check again as the value may have changed while playing back the recording */
-		if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->flags, OPTION_MUSICONHOLD)) {
-			ast_moh_start(conference_bridge_user->chan, conference_bridge_user->opt_args[OPTION_MUSICONHOLD_CLASS], NULL);
-		}
-	} else if (previous_participants == 1) {
-		struct conference_bridge_user *first_participant = AST_LIST_FIRST(&conference_bridge->users_list);
-
-		/* Announce number of users if need be */
-		if (ast_test_flag(&conference_bridge_user->flags, OPTION_ANNOUNCEUSERCOUNT)) {
-			AST_LIST_UNLOCK(&conference_bridges);
-			announce_user_count(conference_bridge, conference_bridge_user);
-			AST_LIST_LOCK(&conference_bridges);
-		}
-
-		/* Temporarily suspend the above participant from the bridge so we have control to stop MOH if needed */
-		if (ast_test_flag(&first_participant->flags, OPTION_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
-			ast_moh_stop(first_participant->chan);
-			ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
-		}
+	/* If the caller is a marked user or is waiting for a marked user to enter pass 'em off, otherwise pass them off to do regular joining stuff */
+	if (ast_test_flag(&conference_bridge_user->flags, OPTION_MARKEDUSER) || ast_test_flag(&conference_bridge_user->flags, OPTION_WAITMARKED)) {
+		post_join_marked(conference_bridge, conference_bridge_user);
 	} else {
-		/* Announce number of users if need be */
-		if (ast_test_flag(&conference_bridge_user->flags, OPTION_ANNOUNCEUSERCOUNT)) {
-			AST_LIST_UNLOCK(&conference_bridges);
-			announce_user_count(conference_bridge, conference_bridge_user);
-			AST_LIST_LOCK(&conference_bridges);
-		}
+		post_join_unmarked(conference_bridge, conference_bridge_user);
 	}
 
 	/* That is that... we are done searchin/modifying the list. */
@@ -282,8 +366,6 @@
  */
 static int leave_conference_bridge(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
 {
-	int previous_participants = 0;
-
 	AST_LIST_LOCK(&conference_bridges);
 
 	/* If this caller is a marked user bump down the count */
@@ -292,24 +374,50 @@
 	}
 
 	/* Decrement the users count while keeping the previous participant count */
-	previous_participants = ast_atomic_fetchadd_int(&conference_bridge->users, -1);
+	ast_atomic_fetchadd_int(&conference_bridge->users, -1);
 
 	/* Drop conference bridge user from the list, they be going bye bye */
 	AST_LIST_REMOVE(&conference_bridge->users_list, conference_bridge_user, list);
 
-	/* If there is still one participant in the conference bridge then start MOH on them if need be, otherwise if we are the last and this is a dynamic conference kill it off. */
-	if (previous_participants == 2) {
+	if (!conference_bridge->users) {
+		/* If there are no more users in this conference we do not have much to do... */
+		if (conference_bridge->dynamic) {
+			/* Unless it is dynamic in which case we delete it. */
+			ast_bridge_destroy(conference_bridge->bridge);
+			AST_LIST_REMOVE(&conference_bridges, conference_bridge, list);
+			ast_free(conference_bridge);
+		}
+	} else if (ast_test_flag(&conference_bridge_user->flags, OPTION_MARKEDUSER) && !conference_bridge->markedusers) {
+		/* Now if they were a marked user and no other marked users exist... we have to mute everyone else and start MOH if need be */
+		struct conference_bridge_user *other_participant = NULL;
+
+		/* Start out with muting everyone */
+		AST_LIST_TRAVERSE(&conference_bridge->users_list, other_participant, list) {
+			other_participant->features.mute = 1;
+		}
+
+		/* Play the audio prompt saying the leader has left the conference */
+		AST_LIST_UNLOCK(&conference_bridges);
+		ast_autoservice_start(conference_bridge_user->chan);
+		play_sound_file(conference_bridge, "conf-leaderhasleft");
+		ast_autoservice_stop(conference_bridge_user->chan);
+		AST_LIST_LOCK(&conference_bridges);
+
+		/* Move on to starting MOH if needed */
+		AST_LIST_TRAVERSE(&conference_bridge->users_list, other_participant, list) {
+			if (ast_test_flag(&other_participant->flags, OPTION_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other_participant->chan)) {
+				ast_moh_start(other_participant->chan, other_participant->opt_args[OPTION_MUSICONHOLD_CLASS], NULL);
+				ast_bridge_unsuspend(conference_bridge->bridge, other_participant->chan);
+			}
+		}
+	} else if (conference_bridge->users == 1) {
+		/* Of course if there is one other person in here we may need to start up MOH on them */
 		struct conference_bridge_user *first_participant = AST_LIST_FIRST(&conference_bridge->users_list);
 
-		/* Temporarily suspend the above participant from the bridge so we have control to start MOH if needed */
 		if (ast_test_flag(&first_participant->flags, OPTION_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
 			ast_moh_start(first_participant->chan, first_participant->opt_args[OPTION_MUSICONHOLD_CLASS], NULL);
 			ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
 		}
-	} else if (previous_participants == 1 && conference_bridge->dynamic) {
-		ast_bridge_destroy(conference_bridge->bridge);
-		AST_LIST_REMOVE(&conference_bridges, conference_bridge, list);
-		ast_free(conference_bridge);
 	}
 
 	AST_LIST_UNLOCK(&conference_bridges);
@@ -387,8 +495,10 @@
 	ast_stopstream(bridge_channel->chan);
 
 	if (digit == '1') {
-		/* 1 - Mute or unmute yourself */
-		conference_bridge_user->features.mute = (!conference_bridge_user->features.mute ? 1 : 0);
+		/* 1 - Mute or unmute yourself, note we only allow manipulation if they aren't waiting for a marked user or if marked users exist */
+		if (!ast_test_flag(&conference_bridge_user->flags, OPTION_WAITMARKED) || conference_bridge->markedusers) {
+			conference_bridge_user->features.mute = (!conference_bridge_user->features.mute ? 1 : 0);
+		}
 		res = ast_stream_and_wait(bridge_channel->chan, (conference_bridge_user->features.mute ? "conf-muted" : "conf-unmuted"), "");
 	} else if (isadmin && digit == '2') {
 		/* 2 - Unlock or lock conference */




More information about the svn-commits mailing list