diff --git a/Makefile b/Makefile
index 86e4a4464936b7e06beb7ab8d005a934a81c0677..8894d28fe84ff274af66ecbee109a7a6d1a66a49 100755
--- a/Makefile
+++ b/Makefile
@@ -476,6 +476,7 @@ bininstall: all
 	rm -f $(DESTDIR)$(ASTVARLIBDIR)/sounds/voicemail
 	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds
 	mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-csv
+	mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-custom
 	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/keys
 	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/firmware
 	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/firmware/iax
diff --git a/UPGRADE.txt b/UPGRADE.txt
index 89f2ed2a55e962b56c3a1dc01a74f3bdaa59fc8d..64836acf57e8e74c9920cab49e55dbbb45774057 100755
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -26,3 +26,10 @@ Applications:
 
 * The CallerPres application has been removed.  Use SetCallerPres 
   instead.  It accepts both numeric and symbolic names.
+
+Queues:
+
+* A queue is now considered empty not only if there are no members but if
+  none of the members are available (e.g. agents not logged on).  To
+  restore the original behavior, use "leavewhenempty=strict" or 
+  "joinwhenempty=strict" instead of "=yes" for those options.
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 9e6ac2d64ba0255a804645e1869e543b66a09705..78783563de56b3189350983da5c07d4155b445a3 100755
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -3,7 +3,7 @@
  *
  * True call queues with optional send URL on answer
  * 
- * Copyright (C) 1999-2004, Digium, Inc.
+ * Copyright (C) 1999-2005, Digium, Inc.
  *
  * Mark Spencer <markster@digium.com>
  *
@@ -14,8 +14,8 @@
  *             Each dynamic agent in each queue is now stored in the astdb.
  *             When asterisk is restarted, each agent will be automatically
  *             readded into their recorded queues. This feature can be
- *             configured with the 'peristent_members=<1|0>' KVP under the
- *             '[general]' group in queues.conf. The default is on.
+ *             configured with the 'persistent_members=<1|0>' setting in the
+ *             '[general]' category in queues.conf. The default is on.
  * 
  * 2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
  *
@@ -123,9 +123,11 @@ static char *descrip =
 "  The optional URL will be sent to the called party if the channel supports\n"
 "it.\n"
 "  The timeout will cause the queue to fail out after a specified number of\n"
-"seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n";
+"seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"
+"  This application sets the following channel variable upon completion:\n"
+"      QUEUESTATUS    The status of the call as a text string, one of\n"
+"             TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL\n";
 
-/* PHM 06/26/03 */
 static char *app_aqm = "AddQueueMember" ;
 static char *app_aqm_synopsis = "Dynamically adds queue members" ;
 static char *app_aqm_descrip =
@@ -176,27 +178,35 @@ static char *app_upqm_descrip =
 static const char *pm_family = "/Queue/PersistentMembers";
 /* The maximum lengh of each persistent member queue database entry */
 #define PM_MAX_LEN 2048
+
 /* queues.conf [general] option */
 static int queue_persistent_members = 0;
+
 /* queues.conf per-queue weight option */
 static int use_weight = 0;
 
+enum queue_result {
+	QUEUE_UNKNOWN = 0,
+	QUEUE_TIMEOUT = 1,
+	QUEUE_JOINEMPTY = 2,
+	QUEUE_LEAVEEMPTY = 3,
+	QUEUE_JOINUNAVAIL = 4,
+	QUEUE_LEAVEUNAVAIL = 5,
+	QUEUE_FULL = 6,
+};
 
-#define QUEUE_FLAG_RINGBACKONLY		(1 << 0)
-#define QUEUE_FLAG_MUSICONHOLD		(1 << 1)
-#define QUEUE_FLAG_DATAQUALITY		(1 << 2)
-#define QUEUE_FLAG_REDIR_IN		(1 << 3)
-#define QUEUE_FLAG_REDIR_OUT		(1 << 4)
-#define QUEUE_FLAG_DISCON_IN		(1 << 5)
-#define QUEUE_FLAG_DISCON_OUT		(1 << 6)
-#define QUEUE_FLAG_MONJOIN		(1 << 7)	/* Should we join the two files when we are done with the call */
-#define QUEUE_FLAG_DEAD			(1 << 8)	/* Whether the queue is dead or not */
-#define QUEUE_FLAG_JOINEMPTY		(1 << 9)	/* Do we care if the queue has no members? */
-#define QUEUE_FLAG_EVENTWHENCALLED	(1 << 10)	/* Generate an event when the agent is called (before pickup) */
-#define QUEUE_FLAG_LEAVEWHENEMPTY	(1 << 11)	/* If all agents leave the queue, remove callers from the queue */
-#define QUEUE_FLAG_REPORTHOLDTIME	(1 << 12)	/* Should we report caller hold time to answering member? */
-#define QUEUE_FLAG_WRAPPED		(1 << 13)	/* Round Robin - wrapped around? */
-#define QUEUE_FLAG_TIMEOUTRESTART 	(1 << 14)	/* Restart timer when member call  */
+const struct { 
+	enum queue_result id;
+	char *text;
+} queue_results[] = {
+	{ QUEUE_UNKNOWN, "UNKNOWN" },
+	{ QUEUE_TIMEOUT, "TIMEOUT" },
+	{ QUEUE_JOINEMPTY,"JOINEMPTY" },
+	{ QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
+	{ QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
+	{ QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
+	{ QUEUE_FULL, "FULL" },
+};
 
 /* We define a custom "local user" structure because we
    use it not only for keeping track of what is in use but
@@ -208,7 +218,6 @@ struct localuser {
 	int stillgoing;
 	int metric;
 	int oldstatus;
-	unsigned int flags;		/* flag bits */
 	time_t lastcall;
 	struct member *member;
 	struct localuser *next;
@@ -244,22 +253,37 @@ struct member {
 	struct member *next;		/* Next member */
 };
 
+/* values used in multi-bit flags in ast_call_queue */
+#define QUEUE_EMPTY_NORMAL 1
+#define QUEUE_EMPTY_STRICT 2
+#define ANNOUNCEHOLDTIME_ALWAYS 1
+#define ANNOUNCEHOLDTIME_ONCE 2
+
 struct ast_call_queue {
-	ast_mutex_t	lock;	
-	char name[80];			/* Name of the queue */
-	char moh[80];			/* Name of musiconhold to be used */
+	ast_mutex_t lock;	
+	char name[80];			/* Name */
+	char moh[80];			/* Music On Hold class to be used */
 	char announce[80];		/* Announcement to play when call is answered */
-	char context[80];		/* Context for this queue */
-	unsigned int flags;		/* flag bits */
-	int strategy;			/* Queueing strategy */
+	char context[80];		/* Exit context */
+	struct {
+		unsigned int monjoin:1;
+		unsigned int dead:1;
+		unsigned int joinempty:2;
+		unsigned int eventwhencalled:1;
+		unsigned int leavewhenempty:2;
+		unsigned int reportholdtime:1;
+		unsigned int wrapped:1;
+		unsigned int timeoutrestart:1;
+		unsigned int announceholdtime:2;
+		unsigned int strategy:3;
+	};
 	int announcefrequency;          /* How often to announce their position */
 	int roundingseconds;            /* How many seconds do we round to? */
-	int announceholdtime;           /* When to announce holdtime: 0 = never, -1 = every announcement, 1 = only once */
-	int holdtime;                   /* Current avg holdtime for this queue, based on recursive boxcar filter */
+	int holdtime;                   /* Current avg holdtime, based on recursive boxcar filter */
 	int callscompleted;             /* Number of queue calls completed */
 	int callsabandoned;             /* Number of queue calls abandoned */
 	int servicelevel;               /* seconds setting for servicelevel*/
-	int callscompletedinsl;         /* Number of queue calls answered with servicelevel*/
+	int callscompletedinsl;         /* Number of calls answered with servicelevel*/
 	char monfmt[8];                 /* Format to use when recording calls */
 	char sound_next[80];            /* Sound file: "Your call is now first in line" (def. queue-youarenext) */
 	char sound_thereare[80];        /* Sound file: "There are currently" (def. queue-thereare) */
@@ -271,26 +295,37 @@ struct ast_call_queue {
 	char sound_thanks[80];          /* Sound file: "Thank you for your patience." (def. queue-thankyou) */
 	char sound_reporthold[80];	/* Sound file: "Hold time" (def. queue-reporthold) */
 
-	int count;			/* How many entries are in the queue */
-	int maxlen;			/* Max number of entries in queue */
+	int count;			/* How many entries */
+	int maxlen;			/* Max number of entries */
 	int wrapuptime;			/* Wrapup Time */
 
 	int retry;			/* Retry calling everyone after this amount of time */
 	int timeout;			/* How long to wait for an answer */
-	int weight;                     /* This queue's respective weight */
+	int weight;                     /* Respective weight */
 	
 	/* Queue strategy things */
 	int rrpos;			/* Round Robin - position */
 	int memberdelay;		/* Seconds to delay connecting member to caller */
 
-	struct member *members;		/* Member channels to be tried */
-	struct queue_ent *head;		/* Start of the actual queue */
+	struct member *members;		/* Head of the list of members */
+	struct queue_ent *head;		/* Head of the list of callers */
 	struct ast_call_queue *next;	/* Next call queue */
 };
 
 static struct ast_call_queue *queues = NULL;
 AST_MUTEX_DEFINE_STATIC(qlock);
 
+static void set_queue_result(struct ast_channel *chan, enum queue_result res)
+{
+	int i;
+
+	for (i = 0; i < sizeof(queue_results) / sizeof(queue_results[0]); i++) {
+		if (queue_results[i].id == res) {
+			pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
+			return;
+		}
+	}
+}
 
 static char *int2strat(int strategy)
 {
@@ -313,8 +348,7 @@ static int strat2int(char *strategy)
 }
 
 /* Insert the 'new' entry after the 'prev' entry of queue 'q' */
-static inline void insert_entry(struct ast_call_queue *q, 
-					struct queue_ent *prev, struct queue_ent *new, int *pos)
+static inline void insert_entry(struct ast_call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
 {
 	struct queue_ent *cur;
 
@@ -333,24 +367,31 @@ static inline void insert_entry(struct ast_call_queue *q,
 	new->opos = *pos;
 }
 
-static int has_no_members(struct ast_call_queue *q)
+enum queue_member_status {
+	QUEUE_NO_MEMBERS,
+	QUEUE_NO_REACHABLE_MEMBERS,
+	QUEUE_NORMAL
+};
+
+static enum queue_member_status get_member_status(const struct ast_call_queue *q)
 {
 	struct member *member;
-	int empty = 1;
-	member = q->members;
-	while(empty && member) {
-		switch(member->status) {
-		case AST_DEVICE_UNAVAILABLE:
+	enum queue_member_status result = QUEUE_NO_MEMBERS;
+
+	for (member = q->members; member; member = member->next) {
+		switch (member->status) {
 		case AST_DEVICE_INVALID:
-			/* Not logged on, etc */
+			/* nothing to do */
+			break;
+		case AST_DEVICE_UNAVAILABLE:
+			result = QUEUE_NO_REACHABLE_MEMBERS;
 			break;
 		default:
-			/* Not empty */
-			empty = 0;
+			return QUEUE_NORMAL;
 		}
-		member = member->next;
 	}
-	return empty;
+	
+	return result;
 }
 
 struct statechange {
@@ -372,7 +413,6 @@ static void *changethread(void *data)
 		*loc = '\0';
 		loc++;
 	} else {
-		ast_log(LOG_WARNING, "Can't change device '%s' with no technology!\n", sc->dev);
 		free(sc);
 		return NULL;
 	}
@@ -432,7 +472,7 @@ static int statechange_queue(const char *dev, int state, void *ign)
 	return 0;
 }
 
-static int join_queue(char *queuename, struct queue_ent *qe)
+static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
 {
 	struct ast_call_queue *q;
 	struct queue_ent *cur, *prev = NULL;
@@ -443,9 +483,17 @@ static int join_queue(char *queuename, struct queue_ent *qe)
 	ast_mutex_lock(&qlock);
 	for (q = queues; q; q = q->next) {
 		if (!strcasecmp(q->name, queuename)) {
+			enum queue_member_status stat;
 			/* This is our one */
 			ast_mutex_lock(&q->lock);
-			if ((!has_no_members(q) || ast_test_flag(q, QUEUE_FLAG_JOINEMPTY)) && (!q->maxlen || (q->count < q->maxlen))) {
+			stat = get_member_status(q);
+			if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
+				*reason = QUEUE_JOINEMPTY;
+			else if ((q->joinempty == QUEUE_EMPTY_NORMAL) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
+				*reason = QUEUE_JOINUNAVAIL;
+			else if (q->maxlen && (q->count >= q->maxlen))
+				*reason = QUEUE_FULL;
+			else {
 				/* There's space for us, put us at the right position inside
 				 * the queue. 
 				 * Take into account the priority of the calling user */
@@ -494,6 +542,7 @@ static void free_members(struct ast_call_queue *q, int all)
 {
 	/* Free non-dynamic members */
 	struct member *curm, *next, *prev;
+
 	curm = q->members;
 	prev = NULL;
 	while(curm) {
@@ -513,6 +562,7 @@ static void free_members(struct ast_call_queue *q, int all)
 static void destroy_queue(struct ast_call_queue *q)
 {
 	struct ast_call_queue *cur, *prev = NULL;
+
 	ast_mutex_lock(&qlock);
 	for (cur = queues; cur; cur = cur->next) {
 		if (cur == q) {
@@ -591,7 +641,8 @@ static int say_position(struct queue_ent *qe)
 
 	/* If the hold time is >1 min, if it's enabled, and if it's not
 	   supposed to be only once and we have already said it, say it */
-	if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) && (!(qe->parent->announceholdtime==1 && qe->last_pos)) ) {
+	if ((avgholdmins+avgholdsecs) > 0 && (qe->parent->announceholdtime) &&
+	    (!(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE) && qe->last_pos)) {
 		res += play_file(qe->chan, qe->parent->sound_holdtime);
 		if(avgholdmins>0) {
 			if (avgholdmins < 2) {
@@ -652,6 +703,7 @@ static void leave_queue(struct queue_ent *qe)
 	struct ast_call_queue *q;
 	struct queue_ent *cur, *prev = NULL;
 	int pos = 0;
+
 	q = qe->parent;
 	if (!q)
 		return;
@@ -683,16 +735,17 @@ ast_log(LOG_NOTICE, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name
 		cur = cur->next;
 	}
 	ast_mutex_unlock(&q->lock);
-	if (ast_test_flag(q, QUEUE_FLAG_DEAD) && !q->count) {	
+	if (q->dead && !q->count) {	
 		/* It's dead and nobody is in it, so kill it */
 		destroy_queue(q);
 	}
 }
 
-static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
+/* Hang up a list of outgoing calls */
+static void hangupcalls(struct localuser *outgoing, struct ast_channel *exception)
 {
-	/* Hang up a tree of stuff */
 	struct localuser *oo;
+
 	while(outgoing) {
 		/* Hangup any existing lines we have open */
 		if (outgoing->chan && (outgoing->chan != exception))
@@ -706,6 +759,7 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception
 static int update_status(struct ast_call_queue *q, struct member *member, int status)
 {
 	struct member *cur;
+
 	/* Since a reload could have taken place, we have to traverse the list to
 		be sure it's still valid */
 	ast_mutex_lock(&q->lock);
@@ -746,10 +800,10 @@ static int update_dial_status(struct ast_call_queue *q, struct member *member, i
 	return update_status(q, member, status);
 }
 
-static int compare_weight(struct ast_call_queue *rq, struct member *member)
-{
 /* traverse all defined queues which have calls waiting and contain this member
    return 0 if no other queue has precedence (higher weight) or 1 if found  */
+static int compare_weight(struct ast_call_queue *rq, struct member *member)
+{
 	struct ast_call_queue *q;
 	struct member *mem;
 	int found = 0;
@@ -780,8 +834,6 @@ static int compare_weight(struct ast_call_queue *rq, struct member *member)
 	return found;
 }
 
-
-
 static int ring_entry(struct queue_ent *qe, struct localuser *tmp, int *busies)
 {
 	int res;
@@ -876,7 +928,7 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp, int *busies)
 		(*busies)++;
 		return 0;
 	} else {
-		if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
+		if (qe->parent->eventwhencalled) {
 			manager_event(EVENT_FLAG_AGENT, "AgentCalled",
 						"AgentCalled: %s\r\n"
 						"ChannelCalling: %s\r\n"
@@ -901,6 +953,7 @@ static int ring_one(struct queue_ent *qe, struct localuser *outgoing, int *busie
 	struct localuser *cur;
 	struct localuser *best;
 	int bestmetric=0;
+
 	do {
 		best = NULL;
 		cur = outgoing;
@@ -946,6 +999,7 @@ static int store_next(struct queue_ent *qe, struct localuser *outgoing)
 	struct localuser *cur;
 	struct localuser *best;
 	int bestmetric=0;
+
 	best = NULL;
 	cur = outgoing;
 	while(cur) {
@@ -964,7 +1018,7 @@ static int store_next(struct queue_ent *qe, struct localuser *outgoing)
 		qe->parent->rrpos = best->metric % 1000;
 	} else {
 		/* Just increment rrpos */
-		if (!ast_test_flag(qe->parent, QUEUE_FLAG_WRAPPED)) {
+		if (qe->parent->wrapped) {
 			/* No more channels, start over */
 			qe->parent->rrpos = 0;
 		} else {
@@ -972,13 +1026,14 @@ static int store_next(struct queue_ent *qe, struct localuser *outgoing)
 			qe->parent->rrpos++;
 		}
 	}
-	ast_clear_flag(qe->parent, QUEUE_FLAG_WRAPPED);
+	qe->parent->wrapped = 0;
 	return 0;
 }
 
 static int valid_exit(struct queue_ent *qe, char digit)
 {
 	char tmp[2];
+
 	if (ast_strlen_zero(qe->context))
 		return 0;
 	tmp[0] = digit;
@@ -994,7 +1049,7 @@ static int valid_exit(struct queue_ent *qe, char digit)
 
 #define AST_MAX_WATCHERS 256
 
-#define BUILD_STATS do { \
+#define BUILD_WATCHERS do { \
 		o = outgoing; \
 		found = -1; \
 		pos = 1; \
@@ -1014,7 +1069,7 @@ static int valid_exit(struct queue_ent *qe, char digit)
 		} \
 	} while(0)
 	
-static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser *outgoing, int *to, struct ast_flags *flags, char *digit, int prebusies)
+static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser *outgoing, int *to, char *digit, int prebusies, int caller_disconnect)
 {
 	char *queue = qe->parent->name;
 	struct localuser *o;
@@ -1034,12 +1089,12 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
 	struct ast_channel *in = qe->chan;
 	
 	while(*to && !peer) {
-		BUILD_STATS;
+		BUILD_WATCHERS;
 		if ((found < 0) && stillgoing && !qe->parent->strategy) {
 			/* On "ringall" strategy we only move to the next penalty level
 			   when *all* ringing phones are done in the current penalty level */
 			ring_one(qe, outgoing, &numbusies);
-			BUILD_STATS;
+			BUILD_WATCHERS;
 		}
 		if (found < 0) {
 			if (numlines == (numbusies + numnochan)) {
@@ -1058,7 +1113,6 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
 					if (option_verbose > 2)
 						ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
 					peer = o;
-					ast_copy_flags(flags, o, QUEUE_FLAG_REDIR_IN | QUEUE_FLAG_REDIR_OUT | QUEUE_FLAG_DISCON_IN | QUEUE_FLAG_DISCON_OUT);
 				}
 			} else if (o->chan && (o->chan == winner)) {
 				if (!ast_strlen_zero(o->chan->call_forward)) {
@@ -1141,11 +1195,9 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
 		    			case AST_CONTROL_ANSWER:
 							/* This is our guy if someone answered. */
 							if (!peer) {
-								ast_copy_flags(flags, o, QUEUE_FLAG_REDIR_IN | QUEUE_FLAG_REDIR_OUT | QUEUE_FLAG_DISCON_IN | QUEUE_FLAG_DISCON_OUT);
 								if (option_verbose > 2)
 									ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
 								peer = o;
-								ast_copy_flags(flags, o, QUEUE_FLAG_REDIR_IN & QUEUE_FLAG_REDIR_OUT & QUEUE_FLAG_DISCON_IN & QUEUE_FLAG_DISCON_OUT);
 							}
 							break;
 						case AST_CONTROL_BUSY:
@@ -1157,7 +1209,7 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
 							ast_hangup(o->chan);
 							o->chan = NULL;
 							if (qe->parent->strategy) {
-								if (ast_test_flag(qe->parent, QUEUE_FLAG_TIMEOUTRESTART))
+								if (qe->parent->timeoutrestart)
 									*to = orig;
 								ring_one(qe, outgoing, &numbusies);
 							}
@@ -1172,7 +1224,7 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
 							ast_hangup(o->chan);
 							o->chan = NULL;
 							if (qe->parent->strategy) {
-								if (ast_test_flag(qe->parent, QUEUE_FLAG_TIMEOUTRESTART))
+								if (qe->parent->timeoutrestart)
 									*to = orig;
 								ring_one(qe, outgoing, &numbusies);
 							}
@@ -1201,7 +1253,7 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
 					ast_hangup(o->chan);
 					o->chan = NULL;
 					if (qe->parent->strategy) {
-						if (ast_test_flag(qe->parent, QUEUE_FLAG_TIMEOUTRESTART))
+						if (qe->parent->timeoutrestart)
 							*to = orig;
 						ring_one(qe, outgoing, &numbusies);
 					}
@@ -1222,7 +1274,7 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser
 				*to=-1;
 				return NULL;
 			}
-			if (f && (f->frametype == AST_FRAME_DTMF) && ast_test_flag(flags, QUEUE_FLAG_DISCON_OUT) && (f->subclass == '*')) {
+			if (f && (f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass == '*')) {
 				if (option_verbose > 3)
 					ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
 				*to=0;
@@ -1264,21 +1316,35 @@ static int is_our_turn(struct queue_ent *qe)
 	return res;
 }
 
-static int wait_our_turn(struct queue_ent *qe, int ringing)
+static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
 {
 	int res = 0;
 
 	/* This is the holding pen for callers 2 through maxlen */
 	for (;;) {
+		enum queue_member_status stat;
+
 		if (is_our_turn(qe))
 			break;
 
 		/* If we have timed out, break out */
-		if (qe->expire && (time(NULL) > qe->expire))
+		if (qe->expire && (time(NULL) > qe->expire)) {
+			*reason = QUEUE_TIMEOUT;
 			break;
+		}
+
+		stat = get_member_status(qe->parent);
 
 		/* leave the queue if no agents, if enabled */
-		if (ast_test_flag(qe->parent, QUEUE_FLAG_LEAVEWHENEMPTY) && has_no_members(qe->parent)) {
+		if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
+			*reason = QUEUE_LEAVEEMPTY;
+			leave_queue(qe);
+			break;
+		}
+
+		/* leave the queue if no reachable agents, if enabled */
+		if ((qe->parent->leavewhenempty == QUEUE_EMPTY_NORMAL) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
+			*reason = QUEUE_LEAVEUNAVAIL;
 			leave_queue(qe);
 			break;
 		}
@@ -1298,6 +1364,7 @@ static int wait_our_turn(struct queue_ent *qe, int ringing)
 static int update_queue(struct ast_call_queue *q, struct member *member)
 {
 	struct member *cur;
+
 	/* Since a reload could have taken place, we have to traverse the list to
 		be sure it's still valid */
 	ast_mutex_lock(&q->lock);
@@ -1324,24 +1391,23 @@ static int calc_metric(struct ast_call_queue *q, struct member *mem, int pos, st
 		break;
 	case QUEUE_STRATEGY_ROUNDROBIN:
 		if (!pos) {
-			if (!ast_test_flag(q, QUEUE_FLAG_WRAPPED)) {
+			if (!q->wrapped) {
 				/* No more channels, start over */
 				q->rrpos = 0;
 			} else {
 				/* Prioritize next entry */
 				q->rrpos++;
 			}
-			ast_clear_flag(q, QUEUE_FLAG_WRAPPED);
+			q->wrapped = 0;
 		}
 		/* Fall through */
 	case QUEUE_STRATEGY_RRMEMORY:
 		if (pos < q->rrpos) {
 			tmp->metric = 1000 + pos;
 		} else {
-			if (pos > q->rrpos) {
+			if (pos > q->rrpos)
 				/* Indicate there is another priority */
-				ast_set_flag(q, QUEUE_FLAG_WRAPPED);
-			}
+				q->wrapped = 1;
 			tmp->metric = pos;
 		}
 		tmp->metric += mem->penalty * 1000000;
@@ -1368,32 +1434,56 @@ static int calc_metric(struct ast_call_queue *q, struct member *mem, int pos, st
 	return 0;
 }
 
-static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverride, char *url, int *go_on)
+static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *go_on)
 {
 	struct member *cur;
 	struct localuser *outgoing=NULL, *tmp = NULL;
 	int to;
-	struct ast_flags flags;
 	char restofit[AST_MAX_EXTENSION];
 	char oldexten[AST_MAX_EXTENSION]="";
 	char oldcontext[AST_MAX_EXTENSION]="";
 	char queuename[256]="";
 	char *newnum;
-	char *options;
 	char *monitorfilename;
 	struct ast_channel *peer;
 	struct ast_channel *which;
 	struct localuser *lpeer;
 	struct member *member;
 	int res = 0, bridge = 0;
-	int zapx = 2;
 	int numbusies = 0;
 	int x=0;
 	char *announce = NULL;
 	char digit = 0;
 	time_t callstart;
 	time_t now;
-	struct ast_bridge_config config;
+	struct ast_bridge_config bridge_config;
+	char nondataquality = 1;
+
+	memset(&bridge_config, 0, sizeof(bridge_config));
+		
+	for (; options && *options; options++)
+		switch (*options) {
+		case 't':
+			ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
+			break;
+		case 'T':
+			ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
+			break;
+		case 'd':
+			nondataquality = 0;
+			break;
+		case 'h':
+			ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
+			break;
+		case 'H':
+			ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
+			break;
+		case 'n':
+			if ((now - qe->start >= qe->parent->timeout))
+				*go_on = 1;
+			break;
+		}
+
 	/* Hold the lock while we setup the outgoing calls */
 	if (use_weight) 
 		ast_mutex_lock(&qlock);
@@ -1408,9 +1498,9 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
 		announce = qe->announce;
 	if (announceoverride && !ast_strlen_zero(announceoverride))
 		announce = announceoverride;
+
 	while(cur) {
-		/* Get a technology/[device:]number pair */
-		tmp = malloc(sizeof(struct localuser));
+		tmp = malloc(sizeof(*tmp));
 		if (!tmp) {
 			ast_mutex_unlock(&qe->parent->lock);
 			if (use_weight) 
@@ -1418,37 +1508,8 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
 			ast_log(LOG_WARNING, "Out of memory\n");
 			goto out;
 		}
-		memset(tmp, 0, sizeof(struct localuser));
+		memset(tmp, 0, sizeof(*tmp));
 		tmp->stillgoing = -1;
-		options = ooptions;
-		for (; options && *options; options++)
-			switch (*options) {
-			case 't':
-				ast_set_flag(tmp, QUEUE_FLAG_REDIR_IN);
-				break;
-			case 'T':
-				ast_set_flag(tmp, QUEUE_FLAG_REDIR_OUT);
-				break;
-			case 'r':
-				ast_set_flag(tmp, QUEUE_FLAG_RINGBACKONLY);
-				break;
-			case 'm':
-				ast_set_flag(tmp, QUEUE_FLAG_MUSICONHOLD);
-				break;
-			case 'd':
-				ast_set_flag(tmp, QUEUE_FLAG_DATAQUALITY);
-				break;
-			case 'h':
-				ast_set_flag(tmp, QUEUE_FLAG_DISCON_IN);
-				break;
-			case 'H':
-				ast_set_flag(tmp, QUEUE_FLAG_DISCON_OUT);
-				break;
-			case 'n':
-			        if ((now - qe->start >= qe->parent->timeout))
-					*go_on = 1;
-				break;
-			}
 		if (option_debug) {
 			if (url)
 				ast_log(LOG_DEBUG, "Queue with URL=%s_\n", url);
@@ -1490,7 +1551,7 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
 	ast_mutex_unlock(&qe->parent->lock);
 	if (use_weight) 
 		ast_mutex_unlock(&qlock);
-	lpeer = wait_for_answer(qe, outgoing, &to, &flags, &digit, numbusies);
+	lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT));
 	ast_mutex_lock(&qe->parent->lock);
 	if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
 		store_next(qe, outgoing);
@@ -1521,20 +1582,16 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
 		   we will always return with -1 so that it is hung up properly after the 
 		   conversation.  */
 		qe->handled++;
-		if (!strcmp(qe->chan->type,"Zap")) {
-			zapx = !ast_test_flag(tmp, QUEUE_FLAG_DATAQUALITY);
-			ast_channel_setoption(qe->chan,AST_OPTION_TONE_VERIFY,&zapx,sizeof(char),0);
-		}			
-		if (!strcmp(peer->type,"Zap")) {
-			zapx = !ast_test_flag(tmp, QUEUE_FLAG_DATAQUALITY);
-			ast_channel_setoption(peer,AST_OPTION_TONE_VERIFY,&zapx,sizeof(char),0);
-		}
+		if (!strcmp(qe->chan->type,"Zap"))
+			ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
+		if (!strcmp(peer->type,"Zap"))
+			ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
 		/* Update parameters for the queue */
 		recalc_holdtime(qe);
 		member = lpeer->member;
-		hanguptree(outgoing, peer);
+		hangupcalls(outgoing, peer);
 		outgoing = NULL;
-		if (announce || ast_test_flag(qe->parent, QUEUE_FLAG_REPORTHOLDTIME) || qe->parent->memberdelay) {
+		if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
 			int res2;
 			res2 = ast_autoservice_start(qe->chan);
 			if (!res2) {
@@ -1546,7 +1603,7 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
 					if (play_file(peer, announce))
 						ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", announce);
 				}
-				if (!res2 && ast_test_flag(qe->parent, QUEUE_FLAG_REPORTHOLDTIME)) {
+				if (!res2 && qe->parent->reportholdtime) {
 					if (!play_file(peer, qe->parent->sound_reporthold)) {
 						int holdtime;
 						time_t now;
@@ -1567,13 +1624,13 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
 				/* Agent must have hung up */
 				ast_log(LOG_WARNING, "Agent on %s hungup on the customer.  They're going to be pissed.\n", peer->name);
 				ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "AGENTDUMP", "%s", "");
-				if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
+				if (qe->parent->eventwhencalled) {
 					manager_event(EVENT_FLAG_AGENT, "AgentDump",
-							"Queue: %s\r\n"
-							"Uniqueid: %s\r\n"
-							"Channel: %s\r\n"
-							"Member: %s\r\n",
-						queuename, qe->chan->uniqueid, peer->name, member->interface);
+						      "Queue: %s\r\n"
+						      "Uniqueid: %s\r\n"
+						      "Channel: %s\r\n"
+						      "Member: %s\r\n",
+						      queuename, qe->chan->uniqueid, peer->name, member->interface);
 				}
 				ast_hangup(peer);
 				goto out;
@@ -1602,80 +1659,68 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
 		/* Begin Monitoring */
 		if (qe->parent->monfmt && *qe->parent->monfmt) {
 			monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
-			if(pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper( qe->chan, "MONITOR_EXEC_ARGS"))
+			if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS"))
 				which = qe->chan;
 			else
 				which = peer;
-			if(monitorfilename) {
+			if (monitorfilename)
 				ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
-			} else {
+			else
 				ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
-			}
-			if(ast_test_flag(qe->parent, QUEUE_FLAG_MONJOIN)) {
+			if (qe->parent->monjoin)
 				ast_monitor_setjoinfiles(which, 1);
-			}
 		}
 		/* Drop out of the queue at this point, to prepare for next caller */
 		leave_queue(qe);			
- 		if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
+ 		if (url && !ast_strlen_zero(url) && ast_channel_supports_html(peer)) {
 			if (option_debug)
 	 			ast_log(LOG_DEBUG, "app_queue: sendurl=%s.\n", url);
- 			ast_channel_sendurl( peer, url );
+ 			ast_channel_sendurl(peer, url);
  		}
 		ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "CONNECT", "%ld", (long)time(NULL) - qe->start);
-		if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
+		if (qe->parent->eventwhencalled)
 			manager_event(EVENT_FLAG_AGENT, "AgentConnect",
-					"Queue: %s\r\n"
-					"Uniqueid: %s\r\n"
-					"Channel: %s\r\n"
-					"Member: %s\r\n"
-					"Holdtime: %ld\r\n",
-				queuename, qe->chan->uniqueid, peer->name, member->interface, (long)time(NULL) - qe->start);
-		}
+				      "Queue: %s\r\n"
+				      "Uniqueid: %s\r\n"
+				      "Channel: %s\r\n"
+				      "Member: %s\r\n"
+				      "Holdtime: %ld\r\n",
+				      queuename, qe->chan->uniqueid, peer->name, member->interface,
+				      (long)time(NULL) - qe->start);
 		strncpy(oldcontext, qe->chan->context, sizeof(oldcontext) - 1);
 		strncpy(oldexten, qe->chan->exten, sizeof(oldexten) - 1);
 		time(&callstart);
 
-		memset(&config,0,sizeof(struct ast_bridge_config));
-		
-		if (ast_test_flag(&flags, QUEUE_FLAG_REDIR_IN))
-			ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
-		if (ast_test_flag(&flags, QUEUE_FLAG_REDIR_OUT))
-			ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
-		if (ast_test_flag(&flags, QUEUE_FLAG_DISCON_IN))
-			ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
-		if (ast_test_flag(&flags, QUEUE_FLAG_DISCON_OUT))
-			ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
-		bridge = ast_bridge_call(qe->chan,peer,&config);
+		bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
 
 		if (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten)) {
 			ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "TRANSFER", "%s|%s", qe->chan->exten, qe->chan->context);
 		} else if (qe->chan->_softhangup) {
-			ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETECALLER", "%ld|%ld", (long)(callstart - qe->start), (long)(time(NULL) - callstart));
-			if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
+			ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETECALLER", "%ld|%ld",
+				      (long)(callstart - qe->start), (long)(time(NULL) - callstart));
+			if (qe->parent->eventwhencalled)
 				manager_event(EVENT_FLAG_AGENT, "AgentComplete",
-						"Queue: %s\r\n"
-						"Uniqueid: %s\r\n"
-						"Channel: %s\r\n"
-						"Member: %s\r\n"
-						"HoldTime: %ld\r\n"
-						"TalkTime: %ld\r\n"
-						"Reason: caller\r\n",
-						queuename, qe->chan->uniqueid, peer->name, member->interface, (long)(callstart - qe->start), (long)(time(NULL) - callstart));
-			}
+					      "Queue: %s\r\n"
+					      "Uniqueid: %s\r\n"
+					      "Channel: %s\r\n"
+					      "Member: %s\r\n"
+					      "HoldTime: %ld\r\n"
+					      "TalkTime: %ld\r\n"
+					      "Reason: caller\r\n",
+					      queuename, qe->chan->uniqueid, peer->name, member->interface,
+					      (long)(callstart - qe->start), (long)(time(NULL) - callstart));
 		} else {
 			ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETEAGENT", "%ld|%ld", (long)(callstart - qe->start), (long)(time(NULL) - callstart));
-			if (ast_test_flag(qe->parent, QUEUE_FLAG_EVENTWHENCALLED)) {
+			if (qe->parent->eventwhencalled)
 				manager_event(EVENT_FLAG_AGENT, "AgentComplete",
-						"Queue: %s\r\n"
-						"Uniqueid: %s\r\n"
-						"Channel: %s\r\n"
-						"HoldTime: %ld\r\n"
-						"TalkTime: %ld\r\n"
-						"Reason: agent\r\n",
-					queuename, qe->chan->uniqueid, peer->name, (long)(callstart - qe->start), (long)(time(NULL) - callstart));
-			}
-
+					      "Queue: %s\r\n"
+					      "Uniqueid: %s\r\n"
+					      "Channel: %s\r\n"
+					      "HoldTime: %ld\r\n"
+					      "TalkTime: %ld\r\n"
+					      "Reason: agent\r\n",
+					      queuename, qe->chan->uniqueid, peer->name, (long)(callstart - qe->start),
+					      (long)(time(NULL) - callstart));
 		}
 
 		if(bridge != AST_PBX_NO_HANGUP_PEER)
@@ -1687,7 +1732,7 @@ static int try_calling(struct queue_ent *qe, char *ooptions, char *announceoverr
 			res = bridge; /* bridge error, stay in the queue */
 	}	
 out:
-	hanguptree(outgoing, NULL);
+	hangupcalls(outgoing, NULL);
 	return res;
 }
 
@@ -1695,11 +1740,10 @@ static int wait_a_bit(struct queue_ent *qe)
 {
 	/* Don't need to hold the lock while we setup the outgoing calls */
 	int retrywait = qe->parent->retry * 1000;
+
 	return ast_waitfordigit(qe->chan, retrywait);
 }
 
-/* [PHM 06/26/03] */
-
 static struct member * interface_exists(struct ast_call_queue *q, char *interface)
 {
 	struct member *mem;
@@ -2236,6 +2280,7 @@ static int queue_exec(struct ast_channel *chan, void *data)
 	char *user_priority;
 	int prio;
 	char *queuetimeoutstr = NULL;
+	enum queue_result reason = QUEUE_UNKNOWN;
 
 	/* whether to exit Queue application after the timeout hits */
 	int go_on = 0;
@@ -2274,10 +2319,10 @@ static int queue_exec(struct ast_channel *chan, void *data)
 		if (sscanf(user_priority, "%d", &prio) == 1) {
 			if (option_debug)
 				ast_log(LOG_DEBUG, "%s: Got priority %d from ${QUEUE_PRIO}.\n",
-								chan->name, prio);
+					chan->name, prio);
 		} else {
 			ast_log(LOG_WARNING, "${QUEUE_PRIO}: Invalid value (%s), channel %s.\n",
-							user_priority, chan->name);
+				user_priority, chan->name);
 			prio = 0;
 		}
 	} else {
@@ -2286,23 +2331,20 @@ static int queue_exec(struct ast_channel *chan, void *data)
 		prio = 0;
 	}
 
-	if (options) {
-		if (strchr(options, 'r')) {
-			ringing = 1;
-		}
-	}
+	if (options && (strchr(options, 'r')))
+		ringing = 1;
 
 	if (option_debug)  
 		ast_log(LOG_DEBUG, "queue: %s, options: %s, url: %s, announce: %s, expires: %ld, priority: %d\n",
-				queuename, options, url, announceoverride, (long)qe.expire, (int)prio);
+			queuename, options, url, announceoverride, (long)qe.expire, (int)prio);
 
 	qe.chan = chan;
 	qe.prio = (int)prio;
 	qe.last_pos_said = 0;
 	qe.last_pos = 0;
-	if (!join_queue(queuename, &qe)) {
-		ast_queue_log(queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s", url ? url : "", chan->cid.cid_num ? chan->cid.cid_num : "");
-		/* Start music on hold */
+	if (!join_queue(queuename, &qe, &reason)) {
+		ast_queue_log(queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s", url ? url : "",
+			      chan->cid.cid_num ? chan->cid.cid_num : "");
 check_turns:
 		if (ringing) {
 			ast_indicate(chan, AST_CONTROL_RINGING);
@@ -2312,7 +2354,7 @@ check_turns:
 		for (;;) {
 			/* This is the wait loop for callers 2 through maxlen */
 
-			res = wait_our_turn(&qe, ringing);
+			res = wait_our_turn(&qe, ringing, &reason);
 			/* If they hungup, return immediately */
 			if (res < 0) {
 				/* Record this abandoned call */
@@ -2339,8 +2381,11 @@ check_turns:
 				/* they may dial a digit from the queue context; */
 				/* or, they may timeout. */
 
+				enum queue_member_status stat;
+
 				/* Leave if we have exceeded our queuetimeout */
 				if (qe.expire && (time(NULL) > qe.expire)) {
+					reason = QUEUE_TIMEOUT;
 					res = 0;
 					break;
 				}
@@ -2363,14 +2408,25 @@ check_turns:
 					break;
 				}
 
+				stat = get_member_status(qe.parent);
+
 				/* leave the queue if no agents, if enabled */
-				if (ast_test_flag(qe.parent, QUEUE_FLAG_LEAVEWHENEMPTY) && has_no_members(qe.parent)) {
+				if (qe.parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
+					reason = QUEUE_LEAVEEMPTY;
+					res = 0;
+					break;
+				}
+
+				/* leave the queue if no reachable agents, if enabled */
+				if ((qe.parent->leavewhenempty == QUEUE_EMPTY_NORMAL) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
+					reason = QUEUE_LEAVEUNAVAIL;
 					res = 0;
 					break;
 				}
 
 				/* Leave if we have exceeded our queuetimeout */
 				if (qe.expire && (time(NULL) > qe.expire)) {
+					reason = QUEUE_TIMEOUT;
 					res = 0;
 					break;
 				}
@@ -2396,6 +2452,7 @@ check_turns:
 						res = -1;
 					}
 					ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
+					reason = QUEUE_TIMEOUT;
 					res = 0;
 					break;
 				}
@@ -2422,9 +2479,12 @@ check_turns:
 			ast_stopstream(chan);
 		}
 		leave_queue(&qe);
+		if (reason != QUEUE_UNKNOWN)
+			set_queue_result(chan, reason);
 	} else {
 		ast_log(LOG_WARNING, "Unable to join queue '%s'\n", queuename);
-		res =  0;
+		set_queue_result(chan, reason);
+		res = 0;
 	}
 	LOCAL_USER_REMOVE(u);
 	return res;
@@ -2450,7 +2510,7 @@ static void reload_queues(void)
 	/* Mark all queues as dead for the moment */
 	q = queues;
 	while(q) {
-		ast_set_flag(q, QUEUE_FLAG_DEAD);
+		q->dead = 1;
 		q = q->next;
 	}
 	/* Chug through config file */
@@ -2480,7 +2540,7 @@ static void reload_queues(void)
 				if (!new) 
 					ast_mutex_lock(&q->lock);
 				/* Re-initialize the queue */
-				ast_clear_flag(q, QUEUE_FLAG_DEAD);
+				q->dead = 0;
 				q->retry = DEFAULT_RETRY;
 				q->timeout = -1;
 				q->maxlen = 0;
@@ -2545,7 +2605,7 @@ static void reload_queues(void)
 					} else if (!strcasecmp(var->name, "timeout")) {
 						q->timeout = atoi(var->value);
 					} else if (!strcasecmp(var->name, "monitor-join")) {
-						ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_MONJOIN);
+						q->monjoin = ast_true(var->value);
 					} else if (!strcasecmp(var->name, "monitor-format")) {
 						strncpy(q->monfmt, var->value, sizeof(q->monfmt) - 1);
 					} else if (!strcasecmp(var->name, "queue-youarenext")) {
@@ -2575,7 +2635,12 @@ static void reload_queues(void)
 							q->roundingseconds=0;
 						}
 					} else if (!strcasecmp(var->name, "announce-holdtime")) {
-						q->announceholdtime = (!strcasecmp(var->value,"once")) ? 1 : ast_true(var->value);
+						if (!strcasecmp(var->value, "once"))
+							q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
+						else if (ast_true(var->value))
+							q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
+						else
+							q->announceholdtime = 0;
 					} else if (!strcasecmp(var->name, "retry")) {
 						q->retry = atoi(var->value);
 					} else if (!strcasecmp(var->name, "wrapuptime")) {
@@ -2591,13 +2656,23 @@ static void reload_queues(void)
 							q->strategy = 0;
 						}
 					} else if (!strcasecmp(var->name, "joinempty")) {
-						ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_JOINEMPTY);
+						if (!strcasecmp(var->value, "strict"))
+							q->joinempty = QUEUE_EMPTY_STRICT;
+						else if (ast_true(var->value))
+							q->joinempty = QUEUE_EMPTY_NORMAL;
+						else
+							q->joinempty = 0;
 					} else if (!strcasecmp(var->name, "leavewhenempty")) {
-						ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_LEAVEWHENEMPTY);
+						if (!strcasecmp(var->value, "strict"))
+							q->leavewhenempty = QUEUE_EMPTY_STRICT;
+						else if (ast_true(var->value))
+							q->leavewhenempty = QUEUE_EMPTY_NORMAL;
+						else
+							q->leavewhenempty = 0;
 					} else if (!strcasecmp(var->name, "eventwhencalled")) {
-						ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_EVENTWHENCALLED);
+						q->eventwhencalled = ast_true(var->value);
 					} else if (!strcasecmp(var->name, "reportholdtime")) {
-						ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_REPORTHOLDTIME);
+						q->reportholdtime = ast_true(var->value);
 					} else if (!strcasecmp(var->name, "memberdelay")) {
 						q->memberdelay = atoi(var->value);
 					} else if (!strcasecmp(var->name, "weight")) {
@@ -2605,7 +2680,7 @@ static void reload_queues(void)
 						if (q->weight)
 							use_weight++;
 					} else if (!strcasecmp(var->name, "timeoutrestart")) {
-						ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_TIMEOUTRESTART);
+						q->timeoutrestart = ast_true(var->value);
 					} else {
 						ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queue.conf\n", cat, var->name, var->lineno);
 					}
@@ -2637,7 +2712,7 @@ static void reload_queues(void)
 	ql = NULL;
 	while(q) {
 		qn = q->next;
-		if (ast_test_flag(q, QUEUE_FLAG_DEAD)) {
+		if (q->dead) {
 			if (ql)
 				ql->next = q->next;
 			else
diff --git a/channel.c b/channel.c
index d2ac71a2473a975d9dfc67993717fbd041d35cd6..ba42f9ad247c38aa3307e13a1f4e5d2fe5c2445c 100755
--- a/channel.c
+++ b/channel.c
@@ -2219,14 +2219,14 @@ int ast_channel_supports_html(struct ast_channel *chan)
 	return 0;
 }
 
-int ast_channel_sendhtml(struct ast_channel *chan, int subclass, char *data, int datalen)
+int ast_channel_sendhtml(struct ast_channel *chan, int subclass, const char *data, int datalen)
 {
 	if (chan->tech->send_html)
 		return chan->tech->send_html(chan, subclass, data, datalen);
 	return -1;
 }
 
-int ast_channel_sendurl(struct ast_channel *chan, char *url)
+int ast_channel_sendurl(struct ast_channel *chan, const char *url)
 {
 	if (chan->tech->send_html)
 		return chan->tech->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index 1d592827bf193f16ab6e3e87d22172efa238efb9..9043eaf8cb85520a1ce129748a77aa68f1495993 100755
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -201,7 +201,7 @@ static int agent_hangup(struct ast_channel *ast);
 static int agent_answer(struct ast_channel *ast);
 static struct ast_frame *agent_read(struct ast_channel *ast);
 static int agent_write(struct ast_channel *ast, struct ast_frame *f);
-static int agent_sendhtml(struct ast_channel *ast, int subclass, char *data, int datalen);
+static int agent_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
 static int agent_indicate(struct ast_channel *ast, int condition);
 static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
@@ -450,7 +450,7 @@ static struct ast_frame *agent_read(struct ast_channel *ast)
 	return f;
 }
 
-static int agent_sendhtml(struct ast_channel *ast, int subclass, char *data, int datalen)
+static int agent_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
 {
 	struct agent_pvt *p = ast->tech_pvt;
 	int res = -1;
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 6c852cf018600bef87b284618f2734162d6db8c7..c44dc97f1e633d248795724f8d24b4c8db8c73cd 100755
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -653,11 +653,11 @@ static ast_mutex_t iaxsl[IAX_MAX_CALLS];
 static struct timeval lastused[IAX_MAX_CALLS];
 
 
-static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int);
-static int send_command_locked(unsigned short callno, char, int, unsigned int, char *, int, int);
-static int send_command_immediate(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int);
-static int send_command_final(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int);
-static int send_command_transfer(struct chan_iax2_pvt *, char, int, unsigned int, char *, int);
+static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, const char *, int, int);
+static int send_command_locked(unsigned short callno, char, int, unsigned int, const char *, int, int);
+static int send_command_immediate(struct chan_iax2_pvt *, char, int, unsigned int, const char *, int, int);
+static int send_command_final(struct chan_iax2_pvt *, char, int, unsigned int, const char *, int, int);
+static int send_command_transfer(struct chan_iax2_pvt *, char, int, unsigned int, const char *, int);
 static struct iax2_user *build_user(const char *name, struct ast_variable *v, int temponly);
 static void destroy_user(struct iax2_user *user);
 static int expire_registry(void *data);
@@ -670,9 +670,9 @@ static int iax2_provision(struct sockaddr_in *end, char *dest, const char *templ
 static struct ast_channel *iax2_request(const char *type, int format, void *data, int *cause);
 static int iax2_devicestate(void *data);
 static int iax2_digit(struct ast_channel *c, char digit);
-static int iax2_sendtext(struct ast_channel *c, char *text);
+static int iax2_sendtext(struct ast_channel *c, const char *text);
 static int iax2_sendimage(struct ast_channel *c, struct ast_frame *img);
-static int iax2_sendhtml(struct ast_channel *c, int subclass, char *data, int datalen);
+static int iax2_sendhtml(struct ast_channel *c, int subclass, const char *data, int datalen);
 static int iax2_call(struct ast_channel *c, char *dest, int timeout);
 static int iax2_hangup(struct ast_channel *c);
 static int iax2_answer(struct ast_channel *c);
@@ -681,7 +681,7 @@ static int iax2_write(struct ast_channel *c, struct ast_frame *f);
 static int iax2_indicate(struct ast_channel *c, int condition);
 static int iax2_setoption(struct ast_channel *c, int option, void *data, int datalen);
 static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
-static int iax2_transfer(struct ast_channel *c, char *dest);
+static int iax2_transfer(struct ast_channel *c, const char *dest);
 static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan);
 
 static const struct ast_channel_tech iax2_tech = {
@@ -2487,7 +2487,7 @@ static int iax2_digit(struct ast_channel *c, char digit)
 	return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF, digit, 0, NULL, 0, -1);
 }
 
-static int iax2_sendtext(struct ast_channel *c, char *text)
+static int iax2_sendtext(struct ast_channel *c, const char *text)
 {
 	
 	return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
@@ -2499,7 +2499,7 @@ static int iax2_sendimage(struct ast_channel *c, struct ast_frame *img)
 	return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1);
 }
 
-static int iax2_sendhtml(struct ast_channel *c, int subclass, char *data, int datalen)
+static int iax2_sendhtml(struct ast_channel *c, int subclass, const char *data, int datalen)
 {
 	return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, data, datalen, -1);
 }
@@ -3214,7 +3214,7 @@ static int iax2_indicate(struct ast_channel *c, int condition)
 	return send_command_locked(callno, AST_FRAME_CONTROL, condition, 0, NULL, 0, -1);
 }
 	
-static int iax2_transfer(struct ast_channel *c, char *dest)
+static int iax2_transfer(struct ast_channel *c, const char *dest)
 {
 	unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
 	struct iax_ie_data ied;
@@ -4484,7 +4484,7 @@ static int iax2_write(struct ast_channel *c, struct ast_frame *f)
 	return res;
 }
 
-static int __send_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno, 
+static int __send_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const char *data, int datalen, int seqno, 
 		int now, int transfer, int final)
 {
 	struct ast_frame f;
@@ -4495,16 +4495,16 @@ static int __send_command(struct chan_iax2_pvt *i, char type, int command, unsig
 	f.mallocd = 0;
 	f.offset = 0;
 	f.src = (char *)__FUNCTION__;
-	f.data = data;
+	f.data = (char *)data;
 	return iax2_send(i, &f, ts, seqno, now, transfer, final);
 }
 
-static int send_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
+static int send_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const char *data, int datalen, int seqno)
 {
 	return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
 }
 
-static int send_command_locked(unsigned short callno, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
+static int send_command_locked(unsigned short callno, char type, int command, unsigned int ts, const char *data, int datalen, int seqno)
 {
 	int res;
 	ast_mutex_lock(&iaxsl[callno]);
@@ -4514,25 +4514,25 @@ static int send_command_locked(unsigned short callno, char type, int command, un
 }
 
 #ifdef BRIDGE_OPTIMIZATION
-static int forward_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
+static int forward_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const char *data, int datalen, int seqno)
 {
 	return __send_command(iaxs[i->bridgecallno], type, command, ts, data, datalen, seqno, 0, 0, 0);
 }
 #endif
 
-static int send_command_final(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
+static int send_command_final(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const char *data, int datalen, int seqno)
 {
 	/* It is assumed that the callno has already been locked */
 	iax2_predestroy_nolock(i->callno);
 	return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
 }
 
-static int send_command_immediate(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
+static int send_command_immediate(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const char *data, int datalen, int seqno)
 {
 	return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
 }
 
-static int send_command_transfer(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen)
+static int send_command_transfer(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const char *data, int datalen)
 {
 	return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
 }
diff --git a/channels/chan_local.c b/channels/chan_local.c
index 95b1cdad9774278c56d030060480f5ec4ba2e552..05a20992e4ca0e8114333f4d1f5ec7854a880706 100755
--- a/channels/chan_local.c
+++ b/channels/chan_local.c
@@ -61,7 +61,7 @@ static struct ast_frame *local_read(struct ast_channel *ast);
 static int local_write(struct ast_channel *ast, struct ast_frame *f);
 static int local_indicate(struct ast_channel *ast, int condition);
 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
-static int local_sendhtml(struct ast_channel *ast, int subclass, char *data, int datalen);
+static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
 
 static const struct ast_channel_tech local_tech = {
 	.type = type,
@@ -264,7 +264,7 @@ static int local_digit(struct ast_channel *ast, char digit)
 	return res;
 }
 
-static int local_sendhtml(struct ast_channel *ast, int subclass, char *data, int datalen)
+static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
 {
 	struct local_pvt *p = ast->tech_pvt;
 	int res = -1;
@@ -273,7 +273,7 @@ static int local_sendhtml(struct ast_channel *ast, int subclass, char *data, int
 	ast_mutex_lock(&p->lock);
 	isoutbound = IS_OUTBOUND(ast, p);
 	f.subclass = subclass;
-	f.data = data;
+	f.data = (char *)data;
 	f.datalen = datalen;
 	res = local_queue_frame(p, isoutbound, &f, ast);
 	ast_mutex_unlock(&p->lock);
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index 75e6c669664b275676b42358301c04ce3683b3a1..04f7d675e56e982e035146374407505dd0bcafed 100755
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -120,6 +120,7 @@ static const char config[] = "mgcp.conf";
 
 #define MGCP_DTMF_RFC2833	(1 << 0)
 #define MGCP_DTMF_INBAND	(1 << 1)
+#define MGCP_DTMF_HYBRID	(1 << 2)
 
 #define DEFAULT_MGCP_GW_PORT	2427 /* From RFC 2705 */
 #define DEFAULT_MGCP_CA_PORT	2727 /* From RFC 2705 */
@@ -988,6 +989,8 @@ static int mgcp_hangup(struct ast_channel *ast)
 	if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
 		/* SC: check whether other channel is active. */
 		if (!sub->next->owner) {
+			if (p->dtmfmode & MGCP_DTMF_HYBRID)
+				p->dtmfmode &= ~MGCP_DTMF_INBAND;
 			if (mgcpdebug) {
 				ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
 			}
@@ -1377,7 +1380,7 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
 		if (sub->rtp)
 			tmp->fds[0] = ast_rtp_fd(sub->rtp);
 		tmp->type = type;
-		if (i->dtmfmode & MGCP_DTMF_INBAND) {
+		if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
 			i->dsp = ast_dsp_new();
 			ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
 			/* SC: this is to prevent clipping of dtmf tones during dsp processing */
@@ -2617,6 +2620,10 @@ static void *mgcp_ss(void *data)
 					}
 					ast_setstate(chan, AST_STATE_RING);
 					/*zt_enable_ec(p);*/
+					if (p->dtmfmode & MGCP_DTMF_HYBRID) {
+						p->dtmfmode |= MGCP_DTMF_INBAND;
+						ast_indicate(chan, -1);
+					}
 					res = ast_pbx_run(chan);
 					if (res) {
 						ast_log(LOG_WARNING, "PBX exited non-zero\n");
@@ -3608,6 +3615,8 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
 					dtmfmode = MGCP_DTMF_INBAND;
 				else if (!strcasecmp(v->value, "rfc2833")) 
 					dtmfmode = MGCP_DTMF_RFC2833;
+				else if (!strcasecmp(v->value, "hybrid"))
+					dtmfmode = MGCP_DTMF_HYBRID;
 				else if (!strcasecmp(v->value, "none")) 
 					dtmfmode = 0;
 				else
@@ -3702,6 +3711,8 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
 					e->capability = capability;
 					e->parent = gw;
 					e->dtmfmode = dtmfmode;
+					if (!ep_reload && e->sub->rtp)
+						e->dtmfmode |= MGCP_DTMF_INBAND;
 					e->adsi = adsi;
 					e->type = TYPE_LINE;
 					e->immediate = immediate;
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index 81958e0781d58c9151333706c212e49f636b6a60..62778ed76f4e1ced6d81ab94c8c4851e519d420d 100755
--- a/channels/chan_phone.c
+++ b/channels/chan_phone.c
@@ -139,7 +139,7 @@ static int phone_answer(struct ast_channel *ast);
 static struct ast_frame *phone_read(struct ast_channel *ast);
 static int phone_write(struct ast_channel *ast, struct ast_frame *frame);
 static struct ast_frame *phone_exception(struct ast_channel *ast);
-static int phone_send_text(struct ast_channel *ast, char *text);
+static int phone_send_text(struct ast_channel *ast, const char *text);
 
 static const struct ast_channel_tech phone_tech = {
 	.type = type,
@@ -536,7 +536,7 @@ static struct ast_frame  *phone_read(struct ast_channel *ast)
 	return &p->fr;
 }
 
-static int phone_write_buf(struct phone_pvt *p, char *buf, int len, int frlen)
+static int phone_write_buf(struct phone_pvt *p, const char *buf, int len, int frlen)
 {
 	int res;
 	/* Store as much of the buffer as we can, then write fixed frames */
@@ -567,7 +567,7 @@ static int phone_write_buf(struct phone_pvt *p, char *buf, int len, int frlen)
 	return len;
 }
 
-static int phone_send_text(struct ast_channel *ast, char *text)
+static int phone_send_text(struct ast_channel *ast, const char *text)
 {
     int length = strlen(text);
     return phone_write_buf(ast->tech_pvt, text, length, length) == 
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 023ecd4a0067e4ed0f03451c53ec561581d1685f..4ae182c2239f4c23a94bbf4f372d31f53fea6f70 100755
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -653,9 +653,9 @@ static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int inc,
 static int transmit_invite(struct sip_pvt *p, int sipmethod, int sendsdp, char *auth, char *authheader, char *vxml_url, char *distinctive_ring, char *osptoken, int addsipheaders, int init);
 static int transmit_reinvite_with_sdp(struct sip_pvt *p);
 static int transmit_info_with_digit(struct sip_pvt *p, char digit);
-static int transmit_message_with_text(struct sip_pvt *p, char *text);
-static int transmit_refer(struct sip_pvt *p, char *dest);
-static int sip_sipredirect(struct sip_pvt *p, char *dest);
+static int transmit_message_with_text(struct sip_pvt *p, const char *text);
+static int transmit_refer(struct sip_pvt *p, const char *dest);
+static int sip_sipredirect(struct sip_pvt *p, const char *dest);
 static struct sip_peer *temp_peer(char *name);
 static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader, int sipmethod, int init);
 static void free_old_route(struct sip_route *route);
@@ -670,17 +670,16 @@ static int callevents = 0;
 
 static struct ast_channel *sip_request(const char *type, int format, void *data, int *cause);
 static int sip_devicestate(void *data);
-static int sip_sendtext(struct ast_channel *ast, char *text);
+static int sip_sendtext(struct ast_channel *ast, const char *text);
 static int sip_call(struct ast_channel *ast, char *dest, int timeout);
 static int sip_hangup(struct ast_channel *ast);
 static int sip_answer(struct ast_channel *ast);
 static struct ast_frame *sip_read(struct ast_channel *ast);
 static int sip_write(struct ast_channel *ast, struct ast_frame *frame);
 static int sip_indicate(struct ast_channel *ast, int condition);
-static int sip_transfer(struct ast_channel *ast, char *dest);
+static int sip_transfer(struct ast_channel *ast, const char *dest);
 static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int sip_senddigit(struct ast_channel *ast, char digit);
-static int sip_sendtext(struct ast_channel *ast, char *text);
 static int clear_realm_authentication(struct sip_auth *authlist);                            /* Clear realm authentication list (at reload) */
 static struct sip_auth *add_realm_authentication(struct sip_auth *authlist, char *configuration, int lineno);   /* Add realm authentication in list */
 static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, char *realm);         /* Find authentication for a specific realm */
@@ -1178,7 +1177,7 @@ static char *ditch_braces(char *tmp)
 
 /*--- sip_sendtext: Send SIP MESSAGE text within a call ---*/
 /*      Called from PBX core text message functions */
-static int sip_sendtext(struct ast_channel *ast, char *text)
+static int sip_sendtext(struct ast_channel *ast, const char *text)
 {
 	struct sip_pvt *p = ast->tech_pvt;
 	int debug=sip_debug_test_pvt(p);
@@ -2098,7 +2097,7 @@ static int sip_senddigit(struct ast_channel *ast, char digit)
 
 
 /*--- sip_transfer: Transfer SIP call */
-static int sip_transfer(struct ast_channel *ast, char *dest)
+static int sip_transfer(struct ast_channel *ast, const char *dest)
 {
 	struct sip_pvt *p = ast->tech_pvt;
 	int res;
@@ -3122,7 +3121,7 @@ static int add_blank_header(struct sip_request *req)
 }
 
 /*--- add_line: Add content (not header) to SIP message */
-static int add_line(struct sip_request *req, char *line)
+static int add_line(struct sip_request *req, const char *line)
 {
 	if (req->len >= sizeof(req->data) - 4) {
 		ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
@@ -3573,7 +3572,7 @@ static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_
 }
 
 /*--- add_text: Add text body to SIP message ---*/
-static int add_text(struct sip_request *req, char *text)
+static int add_text(struct sip_request *req, const char *text)
 {
 	/* XXX Convert \n's to \r\n's XXX */
 	int len = strlen(text);
@@ -4603,7 +4602,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, char *auth,
 }
 
 /*--- transmit_message_with_text: Transmit text with SIP MESSAGE method ---*/
-static int transmit_message_with_text(struct sip_pvt *p, char *text)
+static int transmit_message_with_text(struct sip_pvt *p, const char *text)
 {
 	struct sip_request req;
 	reqprep(&req, p, SIP_MESSAGE, 0, 1);
@@ -4612,7 +4611,7 @@ static int transmit_message_with_text(struct sip_pvt *p, char *text)
 }
 
 /*--- transmit_refer: Transmit SIP REFER message ---*/
-static int transmit_refer(struct sip_pvt *p, char *dest)
+static int transmit_refer(struct sip_pvt *p, const char *dest)
 {
 	struct sip_request req;
 	char from[256];
@@ -10633,7 +10632,7 @@ static int sip_getheader(struct ast_channel *chan, void *data)
 /* Called by the transfer() dialplan application through the sip_transfer() */
 /* pbx interface function if the call is in ringing state */
 /* coded by Martin Pycko (m78pl@yahoo.com) */
-static int sip_sipredirect(struct sip_pvt *p, char *dest)
+static int sip_sipredirect(struct sip_pvt *p, const char *dest)
 {
 	char *cdest;
 	char *extension, *host, *port;
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index d10886531347c427ea563dcbd463fbb853314766..c68f0ff488f98c0b1336a19a27868d57455e2f3c 100755
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -299,7 +299,7 @@ static int restart_monitor(void);
 
 static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
 
-static int zt_sendtext(struct ast_channel *c, char *text);
+static int zt_sendtext(struct ast_channel *c, const char *text);
 
 static inline int zt_get_event(int fd)
 {
@@ -615,7 +615,7 @@ static struct zt_pvt {
 
 static struct ast_channel *zt_request(const char *type, int format, void *data, int *cause);
 static int zt_digit(struct ast_channel *ast, char digit);
-static int zt_sendtext(struct ast_channel *c, char *text);
+static int zt_sendtext(struct ast_channel *c, const char *text);
 static int zt_call(struct ast_channel *ast, char *rdest, int timeout);
 static int zt_hangup(struct ast_channel *ast);
 static int zt_answer(struct ast_channel *ast);
@@ -10189,7 +10189,7 @@ int load_module(void)
 	return res;
 }
 
-static int zt_sendtext(struct ast_channel *c, char *text)
+static int zt_sendtext(struct ast_channel *c, const char *text)
 {
 #define	END_SILENCE_LEN 400
 #define	HEADER_MS 50
diff --git a/configs/mgcp.conf.sample b/configs/mgcp.conf.sample
index 2af96c9b317963bd7c627d7de764e260558c2c41..63e7255576b47ff7addeb579424ba8e203304abc 100755
--- a/configs/mgcp.conf.sample
+++ b/configs/mgcp.conf.sample
@@ -45,7 +45,7 @@
 ;
 ;context=local
 ;host=dynamic
-;dtmfmode=none		; DTMF Mode can be 'none', 'rfc2833', or 'inband'.  Default is none.
+;dtmfmode=none		; DTMF Mode can be 'none', 'rfc2833', or 'inband' or 'hybrid' which starts in none and moves to inband.  Default is none.
 ;slowsequence=yes	; The DPH100M does not follow MGCP standards for sequencing
 ;line => aaln/1
 
diff --git a/configs/queues.conf.sample b/configs/queues.conf.sample
index 0c3447ffa8d21cb76ca3064d92abe4c7c2c72589..983b89dcdd17e5b2f2fc98b8e99ef816eef8a673 100755
--- a/configs/queues.conf.sample
+++ b/configs/queues.conf.sample
@@ -122,14 +122,21 @@ persistentmembers = yes
 ;
 ; monitor-join = yes
 ;
-; If you wish to allow queues that have no members currently to be joined, set this to yes
+; This setting controls whether callers can join a queue with no members. There are three
+; choices:
+;
+; yes - callers can join a queue with no members or only unavailable members
+; no - callers cannot join a queue with no members or only unavailable members
+; strict - callers cannot join a queue with no members
 ;
 ; joinempty = yes
 ;
-; If you wish to remove callers from the queue if there are no agents present, set this to yes
+; If you wish to remove callers from the queue when new callers cannot join, set this setting
+; to one of the same choices for 'joinwhenempty'
 ;
 ; leavewhenempty = yes
 ;
+;
 ; Asterisk can generate AgentCalled events when an agent is rung, if this is turned on
 ; (may generate a LOT of extra manager events)
 ;
diff --git a/doc/README.variables b/doc/README.variables
index f65ef29d1620711984625c4f5dd7bee0c55210c8..83d3011dd33e37e248af2a88de052babe7fafca9 100755
--- a/doc/README.variables
+++ b/doc/README.variables
@@ -340,6 +340,8 @@ ${MONITOR_EXEC}		Application to execute after monitoring a call
 ${MONITOR_EXEC_ARGS}	Arguments to application
 ${MONITOR_FILENAME} 	File for monitoring (recording) calls in queue
 ${QUEUE_PRIO}		Queue priority
+${QUEUESTATUS} 		Status of the call, one of:
+			(TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL)
 ${RECORDED_FILE} 	* Recorded file in record()
 ${TALK_DETECED} 	* Result from talkdetect()
 ${TOUCH_MONITOR} 	The filename base to use with Touch Monitor (auto record)
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index a28135c12fe26874ca3c6be20f41773750dca93e..92c50003138ab0a54b8d949753895c283cdfcb90 100755
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -115,13 +115,13 @@ struct ast_channel_tech {
 	int (* const write)(struct ast_channel *chan, struct ast_frame *frame);
 
 	/*! Display or transmit text */
-	int (* const send_text)(struct ast_channel *chan, char *text);
+	int (* const send_text)(struct ast_channel *chan, const char *text);
 
 	/*! Display or send an image */
 	int (* const send_image)(struct ast_channel *chan, struct ast_frame *frame);
 
 	/*! Send HTML data */
-	int (* const send_html)(struct ast_channel *chan, int subclass, char *data, int len);
+	int (* const send_html)(struct ast_channel *chan, int subclass, const char *data, int len);
 
 	/*! Handle an exception, reading a frame */
 	struct ast_frame * (* const exception)(struct ast_channel *chan);
@@ -143,7 +143,7 @@ struct ast_channel_tech {
 	int (* const queryoption)(struct ast_channel *chan, int option, void *data, int *datalen);
 
 	/*! Blind transfer other side */
-	int (* const transfer)(struct ast_channel *chan, char *newdest);
+	int (* const transfer)(struct ast_channel *chan, const char *newdest);
 
 	/*! Write a frame, in standard format */
 	int (* const write_video)(struct ast_channel *chan, struct ast_frame *frame);
@@ -841,11 +841,11 @@ int ast_channel_supports_html(struct ast_channel *channel);
 
 /*! Sends HTML on given channel */
 /*! Send HTML or URL on link.  Returns 0 on success or -1 on failure */
-int ast_channel_sendhtml(struct ast_channel *channel, int subclass, char *data, int datalen);
+int ast_channel_sendhtml(struct ast_channel *channel, int subclass, const char *data, int datalen);
 
 /*! Sends a URL on a given link */
 /*! Send URL on link.  Returns 0 on success or -1 on failure */
-int ast_channel_sendurl(struct ast_channel *channel, char *url);
+int ast_channel_sendurl(struct ast_channel *channel, const char *url);
 
 /*! Defers DTMF */
 /*! Defer DTMF so that you only read things like hangups and audio.  Returns
diff --git a/include/asterisk/tdd.h b/include/asterisk/tdd.h
index 9c5313b8c34af5966519fc453d892dd310f13324..669b68ce95fc25c51ac488bbd5d484aa8c0eb197 100755
--- a/include/asterisk/tdd.h
+++ b/include/asterisk/tdd.h
@@ -35,7 +35,7 @@ extern void tdd_init(void);
  * This function creates a stream of TDD data in ulaw format. It returns the size
  * (in bytes) of the data (if it returns a size of 0, there is probably an error)
 */
-extern int tdd_generate(struct tdd_state *tdd, unsigned char *buf, char *string);
+extern int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *string);
 
 /*! Create a TDD state machine */
 /*!
diff --git a/tdd.c b/tdd.c
index e2a6cc839ccc0db3088c31c16b57dca218e3c0b7..a3664e82ed80bca77fcda99ba1716303740daeaa 100755
--- a/tdd.c
+++ b/tdd.c
@@ -233,7 +233,7 @@ static inline float tdd_getcarrier(float *cr, float *ci, int bit)
 	PUT_TDD_STOP;	/* Stop bit */ \
 } while(0);	
 
-int tdd_generate(struct tdd_state *tdd, unsigned char *buf, char *str)
+int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *str)
 {
 	int bytes=0;
 	int i,x;