diff -u --recursive --new-file asterisk-0.5.0/channel.c.nonstop asterisk-0.5.0/channel.c
--- asterisk-0.5.0/channel.c.nonstop	Fri Oct 31 23:55:33 2003
+++ asterisk-0.5.0/channel.c	Sat Nov  1 10:12:05 2003
@@ -733,7 +733,40 @@
 		chan->generatordata = NULL;
 		chan->generator = NULL;
 		chan->writeinterrupt = 0;
+		chan->streamid = -1;
+#ifdef ZAPTEL_OPTIMIZATIONS
+		ast_settimeout(chan, 0, NULL, NULL);
+#endif
+	}
+}
+
+static int ast_generator_callback(void *data)
+{
+	struct ast_channel *chan = (struct ast_channel *)data;
+	void *tmp;
+	int res;
+	if(!chan->generator)
+		return 0;
+	tmp = chan->generatordata;
+	chan->generatordata = NULL;
+	res = chan->generator->generate(chan, tmp, 320, 160);
+	chan->generatordata = tmp;
+	if (res) {
+		ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
+		ast_deactivate_generator(chan);
+		return 0;
 	}
+	else
+	{
+#ifdef ZAPTEL_OPTIMIZATIONS
+		if (chan->timingfd > -1)
+			ast_settimeout(chan, 160, ast_generator_callback, chan);
+		else
+#endif
+			/*chan->streamid =*/ ast_sched_add(chan->sched, 160/8, ast_generator_callback, chan);
+		return 0;
+	}
+//	return 1;
 }
 
 int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
@@ -748,6 +781,7 @@
 	} else {
 		return -1;
 	}
+	ast_generator_callback(chan);
 	return 0;
 }
 
@@ -801,11 +835,24 @@
 	int *exception, int *outfd, int *ms)
 {
 	/* Wait for x amount of time on a file descriptor to have input.  */
-	struct timeval tv;
+	struct timeval tv, tvstart, tvend, tvcur;
 	fd_set rfds, efds;
 	int res;
 	int x, y, max=-1;
 	struct ast_channel *winner = NULL;
+	struct ast_channel *waiter;
+	int min_wait, cur_wait;
+	
+#if 0
+	gettimeofday(&tvstart, NULL);
+	if (*ms >= 0) {
+		tv.tv_sec = *ms / 1000;
+		tv.tv_usec = (*ms % 1000) * 1000;
+		timeradd(&tvstart, &tv, &tvend);
+	} else
+		tvend.tv_sec = tvend.tv_usec = -1;
+#endif
+
 	if (outfd)
 		*outfd = -1;
 	if (exception)
@@ -825,32 +872,81 @@
 		ast_mutex_unlock(&c[x]->lock);
 	}
 	
-	tv.tv_sec = *ms / 1000;
-	tv.tv_usec = (*ms % 1000) * 1000;
-	FD_ZERO(&rfds);
-	FD_ZERO(&efds);
+	res = -1;
+	do {
+#if 0
+		if(tvend.tv_sec < 0)
+			min_wait = -1;
+		else {
+			gettimeofday(&tvcur, NULL);
+			timersub(&tvend, &tvcur, &tv);
+			min_wait = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+			if(!res && !min_wait)
+				break;
+		}
+#else
+		min_wait = *ms;
+#endif
+		waiter = NULL;
 
-	for (x=0;x<n;x++) {
-		for (y=0;y<AST_MAX_FDS;y++) {
-			if (c[x]->fds[y] > -1) {
-				FD_SET(c[x]->fds[y], &rfds);
-				FD_SET(c[x]->fds[y], &efds);
-				if (c[x]->fds[y] > max)
-					max = c[x]->fds[y];
+		FD_ZERO(&rfds);
+		FD_ZERO(&efds);
+
+		for (x=0;x<n;x++) {
+			for (y=0;y<AST_MAX_FDS;y++) {
+				if (c[x]->fds[y] > -1) {
+					FD_SET(c[x]->fds[y], &rfds);
+					FD_SET(c[x]->fds[y], &efds);
+					if (c[x]->fds[y] > max)
+						max = c[x]->fds[y];
+				}
 			}
+			if (c[x]->sched && (c[x]->streamid < 0)) {
+				cur_wait = ast_sched_wait(c[x]->sched);
+				if ((cur_wait >= 0) && ((min_wait < 0) || (cur_wait < min_wait))) {
+					min_wait = cur_wait;
+					waiter = c[x];
+				}
+			}
+			if(res)
+				CHECK_BLOCKING(c[x]);
 		}
-		CHECK_BLOCKING(c[x]);
-	}
-	for (x=0;x<nfds; x++) {
-		FD_SET(fds[x], &rfds);
-		FD_SET(fds[x], &efds);
-		if (fds[x] > max)
+		for (x=0;x<nfds; x++) {
+			FD_SET(fds[x], &rfds);
+			FD_SET(fds[x], &efds);
+			if (fds[x] > max)
 			max = fds[x];
+		}
+		if (min_wait >= 0) {
+			tv.tv_sec = min_wait / 1000;
+			tv.tv_usec = (min_wait % 1000) * 1000;
+			res = ast_select(max + 1, &rfds, NULL, &efds, &tv);
+		} else
+			res = ast_select(max + 1, &rfds, NULL, &efds, NULL);
+		
+//		ast_log(LOG_DEBUG, "min_wait=%d, tv=(%d,%d), *ms=%d, res=%d\n", min_wait, tv.tv_sec, tv.tv_usec, *ms, res);
+
+		if (!res && waiter && (waiter->sched) && (waiter->streamid < 0)) {
+			waiter->blocking = 0;
+			ast_sched_runq(waiter->sched);
+			CHECK_BLOCKING(waiter);
+		}
+		
+#if 0
+		if(*ms >= 0)
+		{
+			gettimeofday(&tvcur, NULL);
+			timersub(&tvend, &tvcur, &tv);
+			*ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+			if(*ms < 0)
+				*ms = 0;
+		}
+#else
+		if ((min_wait > 0) && (*ms >= 0))
+			*ms -= min_wait - (tv.tv_sec * 1000 + tv.tv_usec / 1000);
+#endif
 	}
-	if (*ms >= 0)
-		res = ast_select(max + 1, &rfds, NULL, &efds, &tv);
-	else
-		res = ast_select(max + 1, &rfds, NULL, &efds, NULL);
+	while(!res && (min_wait >= 0) && (*ms != 0));
 
 	if (res < 0) {
 		for (x=0;x<n;x++) 
@@ -872,6 +968,7 @@
 		for (y=0;y<AST_MAX_FDS;y++) {
 			if (c[x]->fds[y] > -1) {
 				if ((FD_ISSET(c[x]->fds[y], &rfds) || FD_ISSET(c[x]->fds[y], &efds)) && !winner) {
+//					ast_log(LOG_DEBUG, "Available descriptor %d (of %d) of channel %d (%p)\n", y, AST_MAX_FDS, x, c[x]);
 					/* Set exception flag if appropriate */
 					if (FD_ISSET(c[x]->fds[y], &efds))
 						c[x]->exception = 1;
@@ -890,7 +987,18 @@
 			winner = NULL;
 		}
 	}
-	*ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+//	*ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+#if 0
+		if(*ms >= 0)
+		{
+			gettimeofday(&tvcur, NULL);
+			timersub(&tvend, &tvcur, &tv);
+			*ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+			if(*ms < 0)
+				*ms = 0;
+		}
+#endif
+//	ast_log(LOG_DEBUG, "Winner = %p\n", winner);
 	return winner;
 }
 
@@ -1142,6 +1250,7 @@
 	} 
 	ast_mutex_unlock(&chan->lock);
 
+#if 0
 	/* Run any generator sitting on the line */
 	if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) {
 		/* Mask generator data temporarily */
@@ -1156,6 +1265,7 @@
 			ast_deactivate_generator(chan);
 		}
 	}
+#endif
 	if (chan->fin & 0x80000000)
 		ast_frame_dump(chan->name, f, "<<");
 	if ((chan->fin & 0x7fffffff) == 0x7fffffff)
