Index: apps/confbridge/include/confbridge.h
===================================================================
--- apps/confbridge/include/confbridge.h	(revision 368966)
+++ apps/confbridge/include/confbridge.h	(working copy)
@@ -200,6 +200,7 @@
 	struct ast_bridge *bridge;                                        /*!< Bridge structure doing the mixing */
 	struct bridge_profile b_profile;                                  /*!< The Bridge Configuration Profile */
 	unsigned int users;                                               /*!< Number of users present */
+	unsigned int wait_users;										  /*!< Number of users present that must wait for marked users */
 	unsigned int markedusers;                                         /*!< Number of marked users present */
 	unsigned int locked:1;                                            /*!< Is this conference bridge locked? */
 	struct ast_channel *playback_chan;                                /*!< Channel used for playback into the conference bridge */
Index: apps/confbridge/conf_config_parser.c
===================================================================
--- apps/confbridge/conf_config_parser.c	(revision 368966)
+++ apps/confbridge/conf_config_parser.c	(working copy)
@@ -520,6 +520,14 @@
 				var->name, var->lineno, CONFBRIDGE_CONFIG);
 		}
 	}
+
+	/* Display a warning if both marked_user and wait_marked were set to true since they aren't really
+	 * compatible options. */
+	if (ast_test_flag(u_profile, USER_OPT_MARKEDUSER) && ast_test_flag(u_profile, USER_OPT_WAITMARKED)) {
+		ast_log(LOG_WARNING,
+			"wait_marked is set to true for '%s' which is a marked user. This is invalid and could cause odd behavior.\n",
+			u_profile->name);
+	}
 	ao2_unlock(u_profile);
 
 	ao2_ref(u_profile, -1);
Index: apps/app_confbridge.c
===================================================================
--- apps/app_confbridge.c	(revision 368966)
+++ apps/app_confbridge.c	(working copy)
@@ -277,6 +277,7 @@
 static struct ao2_container *conference_bridges;
 
 static int play_sound_file(struct conference_bridge *conference_bridge, const char *filename);
+
 static int play_sound_number(struct conference_bridge *conference_bridge, int say_number);
 static int execute_menu_entry(struct conference_bridge *conference_bridge,
 	struct conference_bridge_user *conference_bridge_user,
@@ -708,25 +709,84 @@
 	ao2_unlock(conference_bridge);
 }
 
-/*!
- * \brief Perform post-joining marked specific actions
- *
- * \param conference_bridge Conference bridge being joined
- * \param conference_bridge_user Conference bridge user joining
- *
- * \return Returns 0 on success, -1 if the user hung up
- */
-static int post_join_marked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
+static int conference_should_pause(struct conference_bridge *conference_bridge) {
+	int actives = conference_bridge->users - conference_bridge->wait_users;
+
+	/* 2 or more forcefully active members? Don't put the conference on hold. */
+	if (actives >= 2) {
+		return 0;
+	}
+
+	/* 2 or more members of any kind and one of them is marked?  Don't put the conference on hold. */
+	if (conference_bridge->users >= 2 && conference_bridge->markedusers) {
+		return 0;
+	}
+
+	/* If none of the above, put the conference on hold. */
+	return 1;
+}
+
+static int post_join_unified(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
 {
+	/* Active users are any users that don't have to wait for a marked user. */
+	int actives = conference_bridge->users - conference_bridge->wait_users;
+	int usermode = 0;
+	int starter = 0;
+
+	/* There are three types of joiners basically... those that are marked (2), those that must wait for marked (0), and regular users (1)
+	 * who just need to have two or more of regular/marked users in the conference for it to start. */
 	if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) {
-		struct conference_bridge_user *other_conference_bridge_user = NULL;
+		usermode = 2;
+	} else if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_WAITMARKED)) {
+		usermode = 1;
+	}
 
-		/* If we are not the first user to join, then the users are already
-		 * in the conference so we do not need to update them. */
-		if (conference_bridge->markedusers >= 2) {
+	/* The first real thing that needs to be done is determining whether this entry is a conference starter or
+	 * if the conference already started. */
+	switch (usermode) {
+		/* Entering user is a wait user (waits for marked or other conference start condition) */
+		case 0:
+		if (conference_bridge->users == 2 && conference_bridge->markedusers) {
+			/* If a wait user is the second user and there is already a marked in the conference, it's a starter. */
+			starter = 1;
+		} else if ((actives >= 2) || ((conference_bridge->users > 2) && (conference_bridge->markedusers))) {
+			/* If there are 2 or more actives or if there more than 2 of any kind and at least one is marked,
+			 * we know the conference is already active, so we can back out. */
 			return 0;
 		}
+		break;
 
+		/* Entering user is a normal user (just needs two non-wait users to start conference) */
+		case 1:
+		if ((!conference_bridge->markedusers && actives == 2) || (conference_bridge->markedusers && conference_bridge->users == 2)) {
+			/* With no marked users in the bridge, if it's the second nonwaiter, it's a starter.
+			 * With a marked user in the bridge, it's a starter if and only if it's the second user in the conference. */
+			starter = 1;
+		} else if (actives >= 2) {
+			/* If and only if it wasn't a starter and there are 2 or more actives, the conference already started, so back out. */
+			return 0;
+		}
+		break;
+
+		/* Entering user is a marked user (conference just needs two people in it to start regardless when one is marked) */
+		case 2:
+		if (conference_bridge->users == 2 ||
+			(conference_bridge->users > 2 && (conference_bridge->markedusers == 1 && (actives == 1 || actives == 2) ) )) {
+			/* If a marked user is the second user in the conference or
+			 * the anything later than second and is the only marked user and the first or second active user the conference,
+			 * it's a starter. Ok, this condition is rather nuts. */
+			starter = 1;
+		} else if (conference_bridge->users > 2) {
+			/* If we aren't a starter and there are already more than 2 users, we know it's already started and can back out. */
+			return 0;
+		}
+		break;
+	}
+
+	/* Startup stuff - Unmute other people on the line and start take people out of MOH */
+	if (starter) {
+		struct conference_bridge_user *other_conference_bridge_user = NULL;
+
 		/* 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) {
@@ -739,17 +799,7 @@
 			}
 		}
 
-		/* Next play the audio file stating they are going to be placed into the conference */
-		if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) {
-			if (play_prompt_to_channel(conference_bridge,
-				conference_bridge_user->chan,
-				conf_get_sound(CONF_SOUND_PLACE_IN_CONF, conference_bridge_user->b_profile.sounds))) {
-				/* user hungup while the sound was playing */
-				return -1;
-			}
-		}
-
-		/* Finally iterate through and unmute them all */
+		/* Then 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;
@@ -759,97 +809,64 @@
 				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 0;
+
+		/* If the option to do so is set, we announce the user count to each participant. */
+		if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) &&
+			(conference_bridge->users > conference_bridge_user->u_profile.announce_user_count_all_after)) {
+			ao2_unlock(conference_bridge);
+			if (announce_user_count(conference_bridge, NULL)) {
+				ao2_lock(conference_bridge);
+				return -1;
+			}
+			ao2_lock(conference_bridge);
 		}
-		/* 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 */
+
+		/* Once we are done modifying the other users, we go ahead and return success */
+		return 0;
+	}
+
+	/* Prompting and setting MOH */
+	/* Use regular prompt for regular users and marked users. */
+	if (usermode > 0) {
 		if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) {
 			if (play_prompt_to_channel(conference_bridge,
 				conference_bridge_user->chan,
-				conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, conference_bridge_user->b_profile.sounds))) {
+				conf_get_sound(CONF_SOUND_PLACE_IN_CONF, conference_bridge_user->b_profile.sounds))) {
 				/* user hungup while the sound was playing */
 				return -1;
 			}
 		}
-		/* Start music on hold if needed */
-		/* We need to recheck the markedusers value here. play_prompt_to_channel unlocks the conference bridge, potentially
-		 * allowing a marked user to enter while the prompt was playing
-		 */
-		if (!conference_bridge->markedusers && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) {
-			ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL);
-			conference_bridge_user->playing_moh = 1;
-		}
-	}
-	return 0;
-}
-
-/*!
- * \brief Perform post-joining non-marked specific actions
- *
- * \param conference_bridge Conference bridge being joined
- * \param conference_bridge_user Conference bridge user joining
- *
- * \return Returns 0 on success, -1 if the user hung up
- */
-static int 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->u_profile, USER_OPT_QUIET | USER_OPT_NOONLYPERSON)) {
+	} else {
+		/* Wait users are told they need to wait for a leader. */
+		if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) {
 			if (play_prompt_to_channel(conference_bridge,
 				conference_bridge_user->chan,
-				conf_get_sound(CONF_SOUND_ONLY_PERSON, conference_bridge_user->b_profile.sounds))) {
+				conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, conference_bridge_user->b_profile.sounds))) {
 				/* user hungup while the sound was playing */
 				return -1;
 			}
 		}
-		/* 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
-		 * participant could have joined while the above prompt was playing for the first user.
-		 */
-		if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) {
-			ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL);
-			conference_bridge_user->playing_moh = 1;
-		}
-		return 0;
 	}
 
-	/* Announce number of users if need be */
-	if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) {
-		ao2_unlock(conference_bridge);
-		if (announce_user_count(conference_bridge, conference_bridge_user)) {
-			ao2_lock(conference_bridge);
+	/* If the user is alone in the conference, let them know. */
+	if ((conference_bridge->users == 1) && (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET | USER_OPT_NOONLYPERSON))) {
+		if (play_prompt_to_channel(conference_bridge,
+			conference_bridge_user->chan,
+			conf_get_sound(CONF_SOUND_ONLY_PERSON, conference_bridge_user->b_profile.sounds))) {
+			/* user hungup while the sound was playing */
 			return -1;
 		}
-		ao2_lock(conference_bridge);
 	}
 
-	/* 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->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
-			first_participant->playing_moh = 0;
-			ast_moh_stop(first_participant->chan);
-			ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
-		}
+	/* Start music on hold if needed */
+	/* We need to reevaluate whether we really shouldn't start the conference right now since someone else
+	 * might have started the conference while prompts were playing
+	 */
+	if (conference_should_pause(conference_bridge) && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) {
+		ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL);
+		conference_bridge_user->playing_moh = 1;
 	}
 
-	if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) &&
-		(conference_bridge->users > conference_bridge_user->u_profile.announce_user_count_all_after)) {
-		ao2_unlock(conference_bridge);
-		if (announce_user_count(conference_bridge, NULL)) {
-			ao2_lock(conference_bridge);
-			return -1;
-		}
-		ao2_lock(conference_bridge);
-	}
 	return 0;
 }
 
@@ -988,24 +1005,21 @@
 		conference_bridge->markedusers++;
 	}
 
+	/* If the caller doesn't wait for marked users, bump up the non waiting count */
+	if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_WAITMARKED)) {
+		conference_bridge->wait_users++;
+	}
+
 	/* Set the device state for this conference */
 	if (conference_bridge->users == 1) {
 		ast_devstate_changed(AST_DEVICE_INUSE, "confbridge:%s", conference_bridge->name);
 	}
 
-	/* 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->u_profile, USER_OPT_MARKEDUSER | USER_OPT_WAITMARKED)) {
-		if (post_join_marked(conference_bridge, conference_bridge_user)) {
-			ao2_unlock(conference_bridge);
-			leave_conference_bridge(conference_bridge, conference_bridge_user);
-			return NULL;
-		}
-	} else {
-		if (post_join_unmarked(conference_bridge, conference_bridge_user)) {
-			ao2_unlock(conference_bridge);
-			leave_conference_bridge(conference_bridge, conference_bridge_user);
-			return NULL;
-		}
+	/* Post Join Operations */
+	if (post_join_unified(conference_bridge, conference_bridge_user)) {
+		ao2_unlock(conference_bridge);
+		leave_conference_bridge(conference_bridge, conference_bridge_user);
+		return NULL;
 	}
 
 	/* check to see if recording needs to be started or not */
@@ -1038,6 +1052,11 @@
 		conference_bridge->markedusers--;
 	}
 
+	/* If this caller is a non-waiting user, bump down the non_wait_users count */
+	if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_WAITMARKED)) {
+		conference_bridge->wait_users--;
+	}
+
 	/* Decrement the users count while keeping the previous participant count */
 	conference_bridge->users--;
 
@@ -1049,9 +1068,11 @@
 		if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER) && !conference_bridge->markedusers) {
 			struct conference_bridge_user *other_participant = NULL;
 
-			/* Start out with muting everyone */
+			/* Start out with muting wait on marked users */
 			AST_LIST_TRAVERSE(&conference_bridge->users_list, other_participant, list) {
-				other_participant->features.mute = 1;
+				if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_WAITMARKED)) {
+					other_participant->features.mute = 1;
+				}
 			}
 
 			/* Play back the audio prompt saying the leader has left the conference */
@@ -1069,21 +1090,31 @@
 				if (ast_test_flag(&other_participant->u_profile, USER_OPT_ENDMARKED)) {
 					other_participant->kicked = 1;
 					ast_bridge_remove(conference_bridge->bridge, other_participant->chan);
-				} else if (ast_test_flag(&other_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other_participant->chan)) {
+				} else if (ast_test_flag(&other_participant->u_profile, USER_OPT_WAITMARKED) &&
+					ast_test_flag(&other_participant->u_profile, USER_OPT_MUSICONHOLD) &&
+					!ast_bridge_suspend(conference_bridge->bridge, other_participant->chan)) {
+
 					ast_moh_start(other_participant->chan, other_participant->u_profile.moh_class, NULL);
 					other_participant->playing_moh = 1;
 					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);
+		}
+		if (conference_should_pause(conference_bridge)) {
+			/* If the conference pause evaluater determines the conference needs to pause while waiting for another marked user/more non-waiters
+			 * then we need the remaining members to be muted and go into music on hold. */
+			struct conference_bridge_user *other;
 
-			if (ast_test_flag(&first_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
-				ast_moh_start(first_participant->chan, first_participant->u_profile.moh_class, NULL);
-				first_participant->playing_moh = 1;
-				ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
+			AST_LIST_TRAVERSE(&conference_bridge->users_list, other, list) {
+				other->features.mute = 1;
+
+				if (ast_test_flag(&other->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other->chan)) {
+					ast_moh_start(other->chan, other->u_profile.moh_class, NULL);
+					other->playing_moh = 1;
+					ast_bridge_unsuspend(conference_bridge->bridge, other->chan);
+				}
 			}
+
 		}
 	} else {
 		/* Set device state to "not in use" */
@@ -2351,13 +2382,15 @@
 		"Conference: %s\r\n"
 		"Parties: %d\r\n"
 		"Marked: %d\r\n"
+		"Wait Marked: %d\r\n"
 		"Locked: %s\r\n"
 		"\r\n",
 		id_text,
 		bridge->name,
 		bridge->users,
+		bridge->wait_users,
 		bridge->markedusers,
-		bridge->locked ? "Yes" : "No"); 
+		bridge->locked ? "Yes" : "No");
 		ao2_unlock(bridge);
 
 		ao2_ref(bridge, -1);

