Index: apps/app_queue.c
===================================================================
--- apps/app_queue.c	(revision 424092)
+++ apps/app_queue.c	(working copy)
@@ -287,6 +287,7 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
@@ -328,6 +329,7 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
@@ -365,6 +367,7 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
@@ -409,6 +412,7 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
@@ -450,6 +454,7 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
@@ -481,6 +486,7 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
@@ -535,6 +541,7 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
@@ -591,6 +598,7 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
@@ -618,6 +626,7 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
@@ -644,11 +653,38 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
 		
 	
+	
+		
+			Return first caller channel in a queue
+		
+		
+			
+		
+		
+			Returns che first caller channel in the specified queuename.
+		
+		
+			[Queue]
+			[QueueLog]
+			[AddQueueMember]
+			[RemoveQueueMember]
+			[PauseQueueMember]
+			[UnpauseQueueMember]
+			[QUEUE_VARIABLES]
+			[QUEUE_MEMBER]
+			[QUEUE_MEMBER_COUNT]
+			[QUEUE_EXISTS]
+			[QUEUE_WAITING_COUNT]
+			[QUEUE_MEMBER_LIST]
+			[QUEUE_MEMBER_PENALTY]
+		
+	
 	
 		
 			Count number of calls currently waiting in a queue.
@@ -670,6 +706,7 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
@@ -696,6 +733,7 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
@@ -724,6 +762,7 @@
 			[QUEUE_MEMBER]
 			[QUEUE_MEMBER_COUNT]
 			[QUEUE_EXISTS]
+			[QUEUE_GET_FIRSTCHANNEL]
 			[QUEUE_WAITING_COUNT]
 			[QUEUE_MEMBER_LIST]
 			[QUEUE_MEMBER_PENALTY]
@@ -8287,6 +8326,41 @@
 	return 0;
 }
 
+/*! \brief Dialplan function QUEUE_GET_FIRSTCHANNEL() Get first callers channel waiting in a specific queue */
+static int queue_function_queuegetfirstchannel(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+{
+	struct call_queue *q, tmpq = {
+		.name = data,
+	};
+	struct ast_variable *var = NULL;
+
+	buf[0] = '\0';
+
+	if (ast_strlen_zero(data)) {
+		ast_log(LOG_ERROR, "QUEUE_GET_FIRSTCHANNEL requires an argument: queuename\n");
+		return -1;
+	}
+
+	if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE_GET_FIRSTCHANNEL()"))) {
+		ao2_lock(q);
+		if(q->head) {
+			snprintf(buf, len, "%s", ast_channel_name(q->head->chan));
+		}
+		ao2_unlock(q);
+		queue_t_unref(q, "Done with reference in QUEUE_GET_FIRSTCHANNEL()");
+	} else if ((var = ast_load_realtime("queues", "name", data, SENTINEL))) {
+		/* if the queue is realtime but was not found in memory, this
+		 * means that the queue had been deleted from memory since it was
+		 * "dead." This means it has a 0 waiting count
+		 */
+		ast_variables_destroy(var);
+	} else {
+		ast_log(LOG_WARNING, "queue %s was not found\n", data);
+	}
+
+	return 0;
+}
+
 /*! \brief Dialplan function QUEUE_WAITING_COUNT() Get number callers waiting in a specific queue */
 static int queue_function_queuewaitingcount(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 {
@@ -8464,6 +8538,11 @@
 	.read = queue_function_qac_dep,
 };
 
+static struct ast_custom_function queuegetfirstchannel_function = {
+	.name = "QUEUE_GET_FIRSTCHANNEL",
+	.read = queue_function_queuegetfirstchannel,
+};
+
 static struct ast_custom_function queuewaitingcount_function = {
 	.name = "QUEUE_WAITING_COUNT",
 	.read = queue_function_queuewaitingcount,
@@ -10679,6 +10758,7 @@
 	ast_custom_function_unregister(&queuemembercount_function);
 	ast_custom_function_unregister(&queuemembercount_dep);
 	ast_custom_function_unregister(&queuememberlist_function);
+	ast_custom_function_unregister(&queuegetfirstchannel_function);
 	ast_custom_function_unregister(&queuewaitingcount_function);
 	ast_custom_function_unregister(&queuememberpenalty_function);
 
@@ -10779,6 +10859,7 @@
 	err |= ast_custom_function_register(&queuemembercount_function);
 	err |= ast_custom_function_register(&queuemembercount_dep);
 	err |= ast_custom_function_register(&queuememberlist_function);
+	err |= ast_custom_function_register(&queuegetfirstchannel_function);
 	err |= ast_custom_function_register(&queuewaitingcount_function);
 	err |= ast_custom_function_register(&queuememberpenalty_function);