--- app_meetme.c.orig	2004-05-25 21:32:38.546656936 -0400
+++ app_meetme.c	2004-05-25 22:05:54.094287584 -0400
@@ -66,7 +66,10 @@
 "	      Default: conf-background.agi\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"
-"      'a' -- set admin mode\n";
+"      'a' -- set admin mode\n"
+"      'A' -- set wait for admin mode\n"
+"      'h' -- set hangup if admin leave\n"
+"      'r' -- set retry on error\n";
 
 static char *descrip2 =
 "  MeetMeCount(confno[|var]): Plays back the number of users in the specifiedi\n"
@@ -93,6 +96,7 @@
 	int fd;				/* Announcements fd */
 	int zapconf;			/* Zaptel Conf # */
 	int users;			/* Number of active users */
+	int admins;			/* Number of active admin */
         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 */
@@ -130,6 +134,8 @@
 
 #define CONF_SIZE 160
 
+#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 */
 #define CONFFLAG_POUNDEXIT (1 << 3)	/* If set asterisk will exit conference when '#' is pressed */
@@ -140,7 +146,8 @@
 #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 marked with this flag left */
-
+#define CONFFLAG_WAITADMIN (1 << 11)   /* Set to wait for Admin */
+#define CONFFLAG_HANGUPADMIN (1 << 12) /* Set to hangup when Admin Leave */
 
 static int careful_write(int fd, unsigned char *data, int len)
 {
@@ -460,6 +467,7 @@
 	int retryzap;
 	int origfd;
 	int musiconhold = 0;
+	int lastadmin = 0;
 	int firstpass = 0;
 	int ret = -1;
 	int x;
@@ -484,6 +492,9 @@
 	}
 	
 	conf->users++;
+	if (confflags & CONFFLAG_ADMIN)
+		conf->admins++;
+
         if (confflags & CONFFLAG_ADMINEXIT) {
         	if (conf->markedusers == -1) {
         		conf->markedusers = 1;
@@ -518,12 +529,18 @@
 	user->userflags = confflags;
 	user->adminflags = 0;
 	ast_mutex_unlock(&conflock);
-        
-	if (!(confflags & CONFFLAG_QUIET) && conf->users == 1) {
-		if (!ast_streamfile(chan, "conf-onlyperson", chan->language))
-			ast_waitstream(chan, "");
-	}
 
+	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, "");
+	}
+        
 	if (confflags & CONFFLAG_VIDEO) {	
 		/* Set it into linear mode (write) */
 		if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
@@ -639,7 +656,8 @@
 	if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) {
 		firstpass = 1;
 		if (!(confflags & CONFFLAG_QUIET))
-			conf_play(conf, ENTER);
+			if (confflags & CONFFLAG_WAITADMIN && conf->admins >= 1)
+				conf_play(conf, ENTER);
 	}
 
 	if (confflags & CONFFLAG_AGI) {
@@ -678,13 +696,13 @@
 	        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;
 	                
-			/* trying to add moh for single person conf */
-			if (confflags & CONFFLAG_MOH) {
+			if (confflags & CONFFLAG_MOH && ! (confflags & CONFFLAG_WAITADMIN)) {
 				if (conf->users == 1) {
 					if (musiconhold == 0) {
 						ast_moh_start(chan, NULL);
@@ -698,6 +716,58 @@
 				}
 			}
 	                
+			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_HANGUPADMIN)
+							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);
+					}
+				}
+			}					
+	
 	                /* Leave if the last marked user left */
 	                if ((confflags & CONFFLAG_ADMINEXIT) && (conf->markedusers == 0)) {
 	                	ret = 0;
@@ -896,7 +966,8 @@
 		}
 	}
 	if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN))
-		conf_play(conf, LEAVE);
+		if (confflags & CONFFLAG_WAITADMIN && conf->admins == 1 )
+			conf_play(conf, LEAVE);
 
 outrun:
         if (user->user_no) { /* Only cleanup users who really joined! */
@@ -1053,6 +1124,7 @@
 	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;
@@ -1078,6 +1150,8 @@
 		strncpy(confno, tmp, sizeof(confno));
 		if (strlen(confno) == 0) {
 			allowretry = 1;
+		} else {
+			strncpy(originconfno,confno,sizeof(confno));
 		}
 	}
 	if (info)
@@ -1106,6 +1180,12 @@
                         confflags |= CONFFLAG_ADMINEXIT;
 		if (strchr(inflags, 'b'))
 			confflags |= CONFFLAG_AGI;
+		if (strchr(inflags, 'A'))
+			confflags |= CONFFLAG_WAITADMIN;
+		if (strchr(inflags, 'r'))
+			allowretry = 1;
+		if (strchr(inflags, 'h'))
+			confflags |= CONFFLAG_HANGUPADMIN;
 		if (strchr(inflags, 'd'))
 			dynamic = 1;
 		if (strchr(inflags, 'D')) {
@@ -1123,7 +1203,7 @@
 	}
 
 	do {
-		if (retrycnt > 3)
+		if (retrycnt > MAXRETRY)
 			allowretry = 0;
 		if (empty) {
 			int i, map[1024];
@@ -1212,7 +1292,7 @@
 				}
 			}
 		}
-		while (allowretry && (!strlen(confno)) && (++retrycnt < 4)) {
+		while (allowretry && (!strlen(confno)) && (++retrycnt <= MAXRETRY)) {
 			/* Prompt user for conference number */
 			res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0);
 			if (res < 0) {
@@ -1240,8 +1320,9 @@
 						strncpy(pin, the_pin, sizeof(pin) - 1);
 						res = 0;
 					} else {
-						/* Prompt user for pin if pin is required */
 						res = ast_app_getdata(chan, "conf-getpin", pin, sizeof(pin) - 1, 0);
+						if (++retrycnt <= MAXRETRY)
+							res = ast_app_getdata(chan, "conf-getpin", pin, sizeof(pin) - 1, 0);
 					}
 					if (res >= 0) {
 						if (!strcasecmp(pin, cnf->pin)) {
@@ -1255,7 +1336,7 @@
 							if (!res)
 								ast_waitstream(chan, "");
 							res = -1;
-							if (allowretry)
+							if (allowretry && sizeof(originconfno) == 0)
 								strcpy(confno, "");
 						}
 					} else {
