--- app_meetme.c	2004-07-03 19:23:21.000000000 -0400
+++ app_meetme.c.orig	2004-07-03 12:41:02.000000000 -0400
@@ -66,13 +66,12 @@
 "      'v' -- video mode\n"
 "      'q' -- quiet mode (don't play enter/leave sounds)\n"
 "      'M' -- enable music on hold when the conference has a single caller\n"
-"      'x' -- exit the conference if the last admin user left\n"
-"      'w' -- wait until a admin user has entered the conference\n"
+"      'x' -- exit the conference if the last marked user left\n"
+"      'w' -- wait until a marked user has entered the conference\n"
 "      'b' -- run AGI script specified in ${MEETME_AGI_BACKGROUND}\n"
 "         Default: conf-background.agi\n"
-"         (Note: This does not work with non-Zap channels in the same conference)\n"
+"        (Note: This does not work with non-Zap channels in the same conference)\n"
 "      's' -- Present menu (user or admin) when '*' is received ('send' to menu)\n"
-"      'r' -- Allow retry on wrong PIN\n"
 "      'a' -- set admin mode\n";
 
 static char *descrip2 =
@@ -97,18 +96,17 @@
 
 static struct ast_conference {
 	char confno[AST_MAX_EXTENSION];		/* Conference */
-	struct ast_channel *chan;		/* Announcements channel */
-	int fd;					/* Announcements fd */
-	int zapconf;				/* Zaptel Conf # */
-	int users;				/* Number of active users */
-	int admins;				/* Number of admin users */
-	struct ast_conf_user *firstuser;	/* Pointer to the first user struct */
-	struct ast_conf_user *lastuser;		/* Pointer to the last user struct */
-	time_t start;				/* Start time (s) */
-	int isdynamic;				/* Created on the fly? */
-	int locked;			  	/* Is the conference locked? */
-	char pin[AST_MAX_EXTENSION];		/* If protected by a PIN */
-	char pinadmin[AST_MAX_EXTENSION]; 	/* Admin PIN */
+	struct ast_channel *chan;	/* Announcements channel */
+	int fd;				/* Announcements fd */
+	int zapconf;			/* Zaptel Conf # */
+	int users;			/* Number of active users */
+	int markedusers;		  /* Number of marked users */
+	struct ast_conf_user *firstuser;  /* Pointer to the first user struct */
+	struct ast_conf_user *lastuser;   /* Pointer to the last user struct */
+	time_t start;			/* Start time (s) */
+	int isdynamic;			/* Created on the fly? */
+	int locked;			  /* Is the conference locked? */
+	char pin[AST_MAX_EXTENSION];			/* If protected by a PIN */
 	struct ast_conference *next;
 } *confs;
 
@@ -138,7 +136,6 @@
 #define LEAVE	1
 
 #define CONF_SIZE 320
-#define MAXRETRY 3
 
 #define CONFFLAG_ADMIN	(1 << 1)	/* If set the user has admin access on the conference */
 #define CONFFLAG_MONITOR (1 << 2)	/* If set the user can only receive audio from the conference */
@@ -149,8 +146,8 @@
 #define CONFFLAG_VIDEO (1 << 7)		/* Set to enable video mode */
 #define CONFFLAG_AGI (1 << 8)		/* Set to run AGI Script in Background */
 #define CONFFLAG_MOH (1 << 9)		/* Set to have music on hold when user is alone in conference */
-#define CONFFLAG_ADMINEXIT (1 << 10)    /* If set the MeetMe will return if all admin with this flag left */
-#define CONFFLAG_WAITADMIN (1 << 11)		/* If set, the MeetMe will wait until a admin user enters */
+#define CONFFLAG_ADMINEXIT (1 << 10)    /* If set the MeetMe will return if all marked with this flag left */
+#define CONFFLAG_WAITMARKED (1 << 11)		/* If set, the MeetMe will wait until a marked user enters */
 
 
 static int careful_write(int fd, unsigned char *data, int len)
@@ -216,8 +213,7 @@
 			memset(cnf, 0, sizeof(struct ast_conference));
 			strncpy(cnf->confno, confno, sizeof(cnf->confno) - 1);
 			strncpy(cnf->pin, pin, sizeof(cnf->pin) - 1);
-			strncpy(cnf->pinadmin, pin, sizeof(cnf->pinadmin) - 1);
-			cnf->admins = 0;
+			cnf->markedusers = -1;
 			cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo");
 			if (cnf->chan) {
 				cnf->fd = cnf->chan->fds[0];	/* for use by conf_play() */
@@ -277,7 +273,7 @@
 static struct ast_cli_entry cli_show_confs = {
 	{ "show", "conferences", NULL }, confs_show,
 	"Show status of conferences", show_confs_usage, NULL };
-
+	
 static int conf_cmd(int fd, int argc, char **argv) {
 	/* Process the command */
 	struct ast_conference *cnf;
@@ -298,20 +294,18 @@
 	}
 	if (argc == 1) {
 		/* 'MeetMe': List all the conferences */	
-		now = time(NULL);
+	now = time(NULL);
 		cnf = confs;
 		if (!cnf) {
-			ast_cli(fd, "No active MeetMe conferences.\n");
-			return RESULT_SUCCESS;
-		}
-
-		ast_cli(fd, header_format, "Conf Num", "Parties", "Marked", "Activity", "Creation");
-
+		ast_cli(fd, "No active MeetMe conferences.\n");
+		return RESULT_SUCCESS;
+	}
+	ast_cli(fd, header_format, "Conf Num", "Parties", "Marked", "Activity", "Creation");
 		while(cnf) {
-			if (cnf->admins < 0)
+			if (cnf->markedusers < 0)
 				strcpy(cmdline, "N/A ");
 			else 
-				snprintf(cmdline, sizeof(cmdline), "%4.4d", cnf->admins);
+				snprintf(cmdline, sizeof(cmdline), "%4.4d", cnf->markedusers);
 			hr = (now - cnf->start) / 3600;
 			min = ((now - cnf->start) % 3600) / 60;
 			sec = (now - cnf->start) % 60;
@@ -326,7 +320,6 @@
 	}
 	if (argc < 3)
 		return RESULT_SHOWUSAGE;
-
 	strncpy(cmdline, argv[2], 100);	/* Argv 2: conference number */
 	if (strstr(argv[1], "lock")) {	
 		if (strcmp(argv[1], "lock") == 0) {
@@ -478,7 +471,7 @@
 	struct ast_conference *conf = ptr;
 	int res;
 	ast_mutex_lock(&conflock);
-	res = (conf->admins < 0);
+	res = (conf->markedusers < 0);
 	ast_mutex_unlock(&conflock);
 	return res;
 }
@@ -500,18 +493,17 @@
 	int retryzap;
 	int origfd;
 	int musiconhold = 0;
-	int lastadmin = 0;
 	int firstpass = 0;
+	int origquiet;
 	int ret = -1;
 	int x;
 	int menu_active = 0;
 	int using_pseudo = 0;
-	
+
 	struct ast_app *app;
 	char *agifile;
 	char *agifiledefault = "conf-background.agi";
 	char meetmesecs[30];
-	char pin[AST_MAX_EXTENSION];
 
 	ZT_BUFFERINFO bi;
 	char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
@@ -526,10 +518,14 @@
 		goto outrun;
 	}
 	conf->users++;
-
-	if (confflags & CONFFLAG_ADMIN) 
-		conf->admins++;
-
+	if (confflags & CONFFLAG_ADMINEXIT) {
+		if (conf->markedusers == -1) {
+			conf->markedusers = 1;
+		} else {
+			conf->markedusers++;
+		}
+	}
+      
    	ast_mutex_lock(&conflock);
 	if (conf->firstuser == NULL) {
 		/* Fill the first new User struct */
@@ -557,16 +553,38 @@
 	user->userflags = confflags;
 	user->adminflags = 0;
 	ast_mutex_unlock(&conflock);
-	if (confflags & CONFFLAG_QUIET) {
-	} else {
-		if (conf->users == 1 && ! (confflags & CONFFLAG_WAITADMIN))
-			if (!ast_streamfile(chan, "conf-onlyperson", chan->language))
-				ast_waitstream(chan, "");
-
-		if (confflags & CONFFLAG_WAITADMIN && conf->admins == 0)
-			if (!ast_streamfile(chan, "conf-waitforchairman", chan->language))
-				ast_waitstream(chan, "");
- 	}
+	origquiet = confflags & CONFFLAG_QUIET;
+	while((confflags & CONFFLAG_WAITMARKED) && (conf->markedusers < 0)) {
+		confflags &= ~CONFFLAG_QUIET;
+		confflags |= origquiet;
+		/* XXX Announce that we're waiting on the conference lead to join */
+		if (!(confflags & CONFFLAG_QUIET)) {
+			res = ast_streamfile(chan, "vm-dialout", chan->language);
+			if (!res)
+				res = ast_waitstream(chan, "");
+		} else
+			res = 0;
+		/* If we're waiting with hold music, set to silent mode */
+		if (!res) {
+			confflags |= CONFFLAG_QUIET;
+			ast_moh_start(chan, NULL);
+			res = ast_safe_sleep_conditional(chan, 60000, confnonzero, conf);
+			ast_moh_stop(chan);
+		}
+		if (res < 0) {
+			ast_log(LOG_DEBUG, "Got hangup on '%s' already\n", chan->name);
+			goto outrun;
+		}
+	}
+	
+	if (!(confflags & CONFFLAG_QUIET) && conf->users == 1) {
+		if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) {
+			if (ast_waitstream(chan, "") < 0)
+				goto outrun;
+		} else
+			goto outrun;
+	}
+
 	/* Set it into linear mode (write) */
 	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
 		ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name);
@@ -641,7 +659,7 @@
 		}
 	}
 	memset(&ztc, 0, sizeof(ztc));
-
+	/* Add us to the conference */
 	ztc.chan = 0;	
 	ztc.confno = conf->zapconf;
 	if (confflags & CONFFLAG_MONITOR)
@@ -663,11 +681,11 @@
 			"Uniqueid: %s\r\n"
 			"Meetme: %s\r\n",
 			chan->name, chan->uniqueid, conf->confno);
+
 	if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) {
 		firstpass = 1;
 		if (!(confflags & CONFFLAG_QUIET))
-			if (confflags & CONFFLAG_WAITADMIN && conf->admins >= 1)
-				conf_play(conf, ENTER);
+			conf_play(conf, ENTER);
 	}
 
 	if (confflags & CONFFLAG_AGI) {
@@ -703,77 +721,16 @@
 			x = 1;
 			ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
 		}	
-
-		if ( !(confflags & CONFFLAG_QUIET) && conf->admins == 1 && conf->users > 1 && confflags & CONFFLAG_ADMIN ) {
-			ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL);
-			/* user will join the conference */
-		}
 		for(;;) {
 			outfd = -1;
 			ms = -1;
-			lastadmin = conf->admins;
-
 			c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
 			
 			/* Update the struct with the actual confflags */
 			user->userflags = confflags;
 			
-			if (confflags & CONFFLAG_WAITADMIN) {
-				if(conf->admins == 0) {
-					if (lastadmin != 0) {
-						if (!(confflags & CONFFLAG_QUIET))
-							if (!ast_streamfile(chan, "conf-adminhasleft", chan->language))
-								ast_waitstream(chan, "");
-						if(confflags & CONFFLAG_ADMINEXIT)
-							break;
-						else {
-							ztc.confmode = ZT_CONF_CONF;
-							if (ioctl(fd, ZT_SETCONF, &ztc)) {
-								ast_log(LOG_WARNING, "Error setting conference\n");
-								close(fd);
-								goto outrun;
-							}
-						}
-					}
-					if (musiconhold == 0 && confflags & CONFFLAG_MOH) {
-						ast_moh_start(chan, NULL);
-						musiconhold = 1;
-					} else {
-						ztc.confmode = ZT_CONF_CONF;
-						if (ioctl(fd, ZT_SETCONF, &ztc)) {
-							ast_log(LOG_WARNING, "Error setting conference\n");
-							close(fd);
-							goto outrun;
-						}
-					}
-				} else if(conf->admins >= 1 && lastadmin == 0) {
-					if (confflags & CONFFLAG_MONITOR)
-						ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER;
-					else if (confflags & CONFFLAG_TALKER)
-						ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
-					else
-						ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
-					if (ioctl(fd, ZT_SETCONF, &ztc)) {
-						ast_log(LOG_WARNING, "Error setting conference\n");
-						close(fd);
-						goto outrun;
-					}
-					if (musiconhold && confflags & CONFFLAG_MOH) {
-						ast_moh_stop(chan);
-						musiconhold = 0;
-					}
-					if ( !(confflags & CONFFLAG_QUIET)) {
-						if (!ast_streamfile(chan, "conf-placeintoconf", chan->language))
-							ast_waitstream(chan, "");
-						conf_play(conf, ENTER);
-					}
-				}
-			}					
-
-
-
 			/* trying to add moh for single person conf */
-			if (confflags & CONFFLAG_MOH && !( confflags & CONFFLAG_WAITADMIN)) {
+			if (confflags & CONFFLAG_MOH) {
 				if (conf->users == 1) {
 					if (musiconhold == 0) {
 						ast_moh_start(chan, NULL);
@@ -787,13 +744,8 @@
 				}
 			}
 			
-			/* Leave if the last admin user left */
-			if (confflags & CONFFLAG_ADMINEXIT && conf->admins == 0) {
-				if (!(confflags & CONFFLAG_QUIET)) {
-					res = ast_streamfile(chan, "conf-adminhasleft", chan->language);
-					if (!res)
-						res = ast_waitstream(chan, "");
-				}
+			/* Leave if the last marked user left */
+			if (conf->markedusers == 0) {
 				ret = -1;
 				break;
 			}
@@ -818,7 +770,7 @@
 					}
 				}
 				if (user->adminflags & ADMINFLAG_KICKME) {
-					/* You have been kicked. */
+					//You have been kicked.
 					if (!ast_streamfile(chan, "conf-kicked", chan->language))
 						ast_waitstream(chan, "");
 					ret = 0;
@@ -936,41 +888,6 @@
 											ast_waitstream(chan, "");
 									}
 									break;
-								case 2: /* Login as Admin */
-									/* Prompt user for pin if pin is required */
-									res = ast_app_getdata(chan, "conf-getpin", pin, sizeof(pin) - 1, 0);
-									if (res >= 0) {
-										if (!strcasecmp(pin, conf->pinadmin)) {
-											/* Pin correct */
-											if (confflags & CONFFLAG_MONITOR)
-												ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER;
-											else if (confflags & CONFFLAG_TALKER)
-												ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
-											else
-												ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
-											if (ioctl(fd, ZT_SETCONF, &ztc)) {
-												ast_log(LOG_WARNING, "Error setting conference\n");
-												close(fd);
-												goto outrun;
-											}
-											if (musiconhold && confflags & CONFFLAG_MOH) {
-												ast_moh_stop(chan);
-												musiconhold = 0;
-											}
-	
-											confflags |= CONFFLAG_ADMIN;
-											conf->admins++;
-										} else {
-											/* Pin invalid */
-											res = ast_streamfile(chan, "conf-invalidpin", chan->language);
-											if (!res)
-												ast_waitstream(chan, "");
-										}
-										
-									} else {
-										goto outrun;
-									}
-									break;
 								default:
 									menu_active = 0;
 									/* Play an error message! */
@@ -1037,8 +954,8 @@
 			chan->name, chan->uniqueid, conf->confno);
 		prev = NULL;
 		conf->users--;
-		if (confflags & CONFFLAG_ADMIN) 
-			conf->admins--;
+		if (confflags & CONFFLAG_ADMINEXIT) 
+			conf->markedusers--;
 		cur = confs;
 		if (!conf->users) {
 			/* No more users -- close this one out */
@@ -1205,7 +1122,6 @@
 	int res=-1;
 	struct localuser *u;
 	char confno[AST_MAX_EXTENSION] = "";
-	char originconfno[AST_MAX_EXTENSION] = "";
 	int allowretry = 0;
 	int retrycnt = 0;
 	struct ast_conference *cnf;
@@ -1231,8 +1147,6 @@
 		strncpy(confno, tmp, sizeof(confno));
 		if (ast_strlen_zero(confno)) {
 			allowretry = 1;
-		} else {
-			strncpy(originconfno,confno,sizeof(confno));
 		}
 	}
 	if (info)
@@ -1262,9 +1176,7 @@
 		if (strchr(inflags, 'b'))
 			confflags |= CONFFLAG_AGI;
 		if (strchr(inflags, 'w'))
-			confflags |= CONFFLAG_WAITADMIN;
-		if (strchr(inflags, 'r'))
-			allowretry = 1;
+			confflags |= CONFFLAG_WAITMARKED;
 		if (strchr(inflags, 'd'))
 			dynamic = 1;
 		if (strchr(inflags, 'D')) {
@@ -1282,7 +1194,7 @@
 	}
 
 	do {
-		if (retrycnt > MAXRETRY)
+		if (retrycnt > 3)
 			allowretry = 0;
 		if (empty) {
 			int i, map[1024];
@@ -1384,7 +1296,7 @@
 				}
 			}
 		}
-		while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt <= MAXRETRY)) {
+		while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) {
 			/* Prompt user for conference number */
 			res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0);
 			if (res < 0) {
@@ -1413,9 +1325,7 @@
 						res = 0;
 					} else {
 						/* Prompt user for pin if pin is required */
-						if (++retrycnt <= MAXRETRY)
-							res = ast_app_getdata(chan, "conf-getpin", pin, sizeof(pin) - 1, 0);
-
+						res = ast_app_getdata(chan, "conf-getpin", pin, sizeof(pin) - 1, 0);
 					}
 					if (res >= 0) {
 						if (!strcasecmp(pin, cnf->pin)) {
@@ -1429,7 +1339,7 @@
 							if (!res)
 								ast_waitstream(chan, "");
 							res = -1;
-							if (allowretry  && sizeof(originconfno) == 0)
+							if (allowretry)
 								strcpy(confno, "");
 						}
 					} else {
