Index: channels/chan_agent.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_agent.c,v
retrieving revision 1.81
diff -u -r1.81 chan_agent.c
--- channels/chan_agent.c	11 Aug 2004 19:02:46 -0000	1.81
+++ channels/chan_agent.c	21 Sep 2004 14:22:48 -0000
@@ -21,6 +21,8 @@
 #include <asterisk/module.h>
 #include <asterisk/pbx.h>
 #include <asterisk/options.h>
+#include <asterisk/translate.h>
+#include <asterisk/channel_pvt.h>
 #include <asterisk/lock.h>
 #include <asterisk/sched.h>
 #include <asterisk/io.h>
@@ -88,6 +90,8 @@
 static int autologoff;
 static int wrapuptime;
 static int ackcall;
+static char acksound[AST_MAX_BUF] = "";
+static int ackwait = 0;
 
 static int usecnt =0;
 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
@@ -129,6 +133,8 @@
 	struct ast_channel *owner;			/* Agent */
 	char loginchan[80];
 	struct ast_channel *chan;			/* Channel we use */
+	struct ast_trans_pvt *trans;
+	int framecount;
 	struct agent_pvt *next;				/* Agent */
 } *agents = NULL;
 
@@ -304,7 +310,7 @@
 static struct ast_frame  *agent_read(struct ast_channel *ast)
 {
 	struct agent_pvt *p = ast->pvt->pvt;
-	struct ast_frame *f = NULL;
+	struct ast_frame *f = NULL, *f2=NULL;
 	static struct ast_frame null_frame = { AST_FRAME_NULL, };
 	static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
 	ast_mutex_lock(&p->lock); 
@@ -324,6 +330,14 @@
 			/* Note that we don't hangup if it's not a callback because Asterisk will do it
 			   for us when the PBX instance that called login finishes */
 			if (!ast_strlen_zero(p->loginchan)) {
+				if(p && p->chan && p->chan->stream) {
+					ast_closestream(p->chan->stream);
+					p->chan->stream = NULL;
+				}
+				if(p && p->trans) {
+					ast_translator_free_path(p->trans);
+					p->trans = NULL;
+				}
 				ast_hangup(p->chan);
 				if (p->wrapuptime) {
 					gettimeofday(&p->lastdisc, NULL);
@@ -344,16 +358,27 @@
 		if (p->ackcall) {
 			if (option_verbose > 2)
 				ast_verbose(VERBOSE_PREFIX_3 "%s answered, waiting for '#' to acknowledge\n", p->chan->name);
+			p->framecount = 1;
 			/* Don't pass answer along */
 			ast_frfree(f);
 			f = &null_frame;
-	        }
+		}
         else {
 			p->acknowledged = 1;
 			f = &answer_frame;
         }
 	}
+
 	if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
+		if(p && p->chan && p->chan->stream) {
+			ast_closestream(p->chan->stream);
+			p->chan->stream = NULL;
+		}
+		if(p && p->trans) {
+			ast_translator_free_path(p->trans);
+			p->trans = NULL;
+		}
+
 		if (!p->acknowledged) {
 			if (option_verbose > 2)
 				ast_verbose(VERBOSE_PREFIX_3 "%s acknowledged\n", p->chan->name);
@@ -367,6 +392,46 @@
 		ast_frfree(f);
 		f = NULL;
 	}
+
+	/* Turn this code into poor man's generator since we are reading frames at the perfect speed 
+	   just open a stream and pass along the frames from the file while we are waiting for 
+	   the agent to press # or the timeout to occur.
+	*/
+	if(p && ! p->acknowledged) {
+		if(p && ! p->acknowledged && p->chan && !ast_strlen_zero(acksound) && p && p->framecount++ > ackwait && 
+		   ! p->trans && ! p->acknowledged && (ast_openstream(p->chan,acksound, p->chan->language))) {
+			if((f2 = ast_readframe(p->chan->stream))) {
+				if(p->chan->readformat && p->chan->readformat != f2->subclass) 
+					p->trans = ast_translator_build_path(p->chan->readformat, f2->subclass);
+			}
+		}
+		if(p && p->framecount > ackwait && ! p->acknowledged && p->chan && p->chan->stream) {
+			if(!f2) {
+				if(!(f2 = ast_readframe(p->chan->stream))) {
+					/* Reset the stream and the ackwait and play the file again if the time comes. */
+					if(p && p->chan && p->chan->stream) {
+						ast_closestream(p->chan->stream);
+						p->chan->stream = NULL;
+					}
+					if(p && p->trans) {
+						ast_translator_free_path(p->trans);
+						p->trans = NULL;
+					}
+					p->framecount = 0;
+				}
+			}
+			if(f2) {
+				if(p && p->trans && f2->subclass != p->chan->readformat)
+					f2 = ast_translate(p->trans, f2, 1);
+				if(f2) {
+					ast_write(p->chan, f2);
+					ast_frfree(f2);
+					f2 = NULL;
+				}
+			}
+		}
+	}
+
 	CLEANUP(ast,p);
 	ast_mutex_unlock(&p->lock);
 	if (recordagentcalls && f == &answer_frame)
@@ -519,6 +584,14 @@
 	ast->pvt->pvt = NULL;
 	p->app_sleep_cond = 1;
 	p->acknowledged = 0;
+	if(p && p->chan && p->chan->stream) {
+		ast_stopstream(p->chan);
+		p->chan->stream = NULL;
+	}
+	if(p && p->trans) {
+		ast_translator_free_path(p->trans);
+		p->trans = NULL;
+	}
 	if (p->start && (ast->_state != AST_STATE_UP))
 		howlong = time(NULL) - p->start;
 	time(&p->start);
@@ -742,6 +815,8 @@
 		 * can safely use signals for this purpose. The pselect() needs to be
 		 * implemented in the kernel for this.
 		 */
+		p->trans = NULL;
+		p->framecount = 0;
 		p->app_sleep_cond = 0;
 		if( ast_mutex_trylock(&p->app_lock) )
 		{
@@ -812,6 +887,10 @@
 		/* Create the interface list */
 		if (!strcasecmp(v->name, "agent")) {
 			add_agent(v->value, 0);
+		} else if (!strcasecmp(v->name, "acksound")) {
+			strncpy(acksound,v->value,AST_MAX_BUF);
+		} else if (!strcasecmp(v->name, "ackwait")) {
+			ackwait = atoi(v->value);
 		} else if (!strcasecmp(v->name, "group")) {
 			group = ast_get_group(v->value);
 		} else if (!strcasecmp(v->name, "autologoff")) {
