[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