diff --git a/channel.c b/channel.c
index 87d527d37db7b4341b58257f37da931c8661166f..b7c4ff355ecee6bcd44ff6e601abc8909651b452 100755
--- a/channel.c
+++ b/channel.c
@@ -18,9 +18,9 @@
 #include <sys/time.h>
 #include <signal.h>
 #include <errno.h>
-#include <asterisk/lock.h>
 #include <unistd.h>
 #include <math.h>			/* For PI */
+#include <asterisk/pbx.h>
 #include <asterisk/frame.h>
 #include <asterisk/sched.h>
 #include <asterisk/options.h>
@@ -32,6 +32,7 @@
 #include <asterisk/manager.h>
 #include <asterisk/chanvars.h>
 #include <asterisk/linkedlists.h>
+#include <asterisk/indications.h>
 
 
 static int shutting_down = 0;
@@ -132,7 +133,10 @@ void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
 time_t	myt;
 
 	time(&myt);
-	chan->whentohangup = myt + offset;
+        if (offset)
+	  chan->whentohangup = myt + offset;
+        else
+          chan->whentohangup = 0;
 	return;
 }
 
@@ -290,6 +294,8 @@ struct ast_channel *ast_channel_alloc(int needqueue)
 					tmp->streamid = -1;
 					tmp->appl = NULL;
 					tmp->data = NULL;
+					tmp->fin = 0;
+					tmp->fout = 0;
 					headp=&tmp->varshead;
 					ast_pthread_mutex_init(&tmp->lock);
 				        AST_LIST_HEAD_INIT(headp);
@@ -326,6 +332,7 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
 	struct ast_frame *prev, *cur;
 	int blah = 1;
 	int qlen = 0;
+	/* Build us a copy and free the original one */
 	f = ast_frdup(fin);
 	if (!f) {
 		ast_log(LOG_WARNING, "Unable to duplicate frame\n");
@@ -340,6 +347,18 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
 		cur = cur->next;
 		qlen++;
 	}
+	if (qlen  > 128) {
+		if (fin->frametype != AST_FRAME_VOICE) {
+			ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
+			CRASH;
+		} else {
+			ast_log(LOG_DEBUG, "Dropping voice to exceptionally long queue on %s\n", chan->name);
+			ast_frfree(fin);
+			if (lock)
+				ast_pthread_mutex_unlock(&chan->lock);
+			return 0;
+		}
+	}
 	if (prev)
 		prev->next = f;
 	else
@@ -349,9 +368,6 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
 			ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n",
 				chan->name, f->frametype, f->subclass, qlen, strerror(errno));
 	}
-	if (qlen  > 128) {
-		ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
-	}
 	if (lock)
 		ast_pthread_mutex_unlock(&chan->lock);
 	return 0;
@@ -405,6 +421,27 @@ struct ast_channel *ast_channel_walk(struct ast_channel *prev)
 	
 }
 
+int ast_safe_sleep_conditional(	struct ast_channel *chan, int ms,
+								int (*cond)(void*), void *data )
+{
+	struct ast_frame *f;
+
+	while(ms > 0) {
+		if( cond && ((*cond)(data) == 0 ) )
+			return 0;
+		ms = ast_waitfor(chan, ms);
+		if (ms <0)
+			return -1;
+		if (ms > 0) {
+			f = ast_read(chan);
+			if (!f)
+				return -1;
+			ast_frfree(f);
+		}
+	}
+	return 0;
+}
+
 int ast_safe_sleep(struct ast_channel *chan, int ms)
 {
 	struct ast_frame *f;
@@ -462,6 +499,8 @@ void ast_channel_free(struct ast_channel *chan)
 		free(chan->callerid);	
 	if (chan->ani)
 		free(chan->ani);
+	if (chan->rdnis)
+		free(chan->rdnis);
 	pthread_mutex_destroy(&chan->lock);
 	/* Close pipes if appropriate */
 	if ((fd = chan->pvt->alertpipe[0]) > -1)
@@ -488,6 +527,7 @@ void ast_channel_free(struct ast_channel *chan)
 	                                                 
 
 	free(chan->pvt);
+	chan->pvt = NULL;
 	free(chan);
 	PTHREAD_MUTEX_UNLOCK(&chlock);
 }
@@ -516,6 +556,8 @@ int ast_softhangup(struct ast_channel *chan, int cause)
 	return res;
 }
 
+static int ast_do_masquerade(struct ast_channel *original);
+
 static void free_translation(struct ast_channel *clone)
 {
 	if (clone->pvt->writetrans)
@@ -535,7 +577,12 @@ int ast_hangup(struct ast_channel *chan)
 	   if someone is going to masquerade as us */
 	ast_pthread_mutex_lock(&chan->lock);
 	if (chan->masq) {
-		ast_log(LOG_WARNING, "We're getting hung up, but someone is trying to masq into us?!?\n");
+		if (ast_do_masquerade(chan)) 
+			ast_log(LOG_WARNING, "Failed to perform masquerade\n");
+	}
+
+	if (chan->masq) {
+		ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name);
 		ast_pthread_mutex_unlock(&chan->lock);
 		return 0;
 	}
@@ -629,6 +676,8 @@ int ast_answer(struct ast_channel *chan)
 		return res;
 		break;
 	case AST_STATE_UP:
+		if (chan->cdr)
+			ast_cdr_answer(chan->cdr);
 		break;
 	}
 	return 0;
@@ -704,8 +753,6 @@ int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
 	return winner;
 }
 
-static int ast_do_masquerade(struct ast_channel *original);
-
 struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds, 
 	int *exception, int *outfd, int *ms)
 {
@@ -901,8 +948,10 @@ struct ast_frame *ast_read(struct ast_channel *chan)
 		if (chan->exception) {
 			if (chan->pvt->exception) 
 				f = chan->pvt->exception(chan);
-			else
-				ast_log(LOG_WARNING, "Exception flag set, but no exception handler\n");
+			else {
+				ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
+				f = &null_frame;
+			}
 			/* Clear the exception flag */
 			chan->exception = 0;
 		} else
@@ -912,8 +961,14 @@ struct ast_frame *ast_read(struct ast_channel *chan)
 			ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
 	}
 
+
 	if (f && (f->frametype == AST_FRAME_VOICE)) {
-		if (chan->pvt->readtrans) {
+		if (!(f->subclass & chan->nativeformats)) {
+			/* This frame can't be from the current native formats -- drop it on the
+			   floor */
+			ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s since our native format has changed\n", chan->name);
+			f = &null_frame;
+		} else if (chan->pvt->readtrans) {
 			f = ast_translate(chan->pvt->readtrans, f, 1);
 			if (!f)
 				f = &null_frame;
@@ -948,14 +1003,14 @@ struct ast_frame *ast_read(struct ast_channel *chan)
 		int res;
 		tmp = chan->generatordata;
 		chan->generatordata = NULL;
-		res = chan->generator->generate(chan, tmp, f->datalen);
+		res = chan->generator->generate(chan, tmp, f->datalen, f->samples);
 		chan->generatordata = tmp;
 		if (res) {
 			ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
 			ast_deactivate_generator(chan);
 		}
 	}
-
+	chan->fin++;
 	return f;
 }
 
@@ -965,13 +1020,39 @@ int ast_indicate(struct ast_channel *chan, int condition)
 	/* Stop if we're a zombie or need a soft hangup */
 	if (chan->zombie || ast_check_hangup(chan)) 
 		return -1;
-	if (chan->pvt->indicate) {
+	if (chan->pvt->indicate)
 		res = chan->pvt->indicate(chan, condition);
-		if (res)
-			ast_log(LOG_WARNING, "Driver for channel '%s' failed to indicate condition %d\n", chan->name, condition);
-	} else
-		ast_log(LOG_WARNING, "Driver for channel '%s' does not support indication\n", chan->name);
-	return res;
+	if (!chan->pvt->indicate || res) {
+		/*
+		 * Device does not support (that) indication, lets fake
+		 * it by doing our own tone generation. (PM2002)
+		 */
+		if (condition >= 0) {
+			const struct tone_zone_sound *ts = NULL;
+			switch (condition) {
+			 case AST_CONTROL_RINGING:
+				ts = ast_get_indication_tone(chan->zone, "ring");
+				break;
+			 case AST_CONTROL_BUSY:
+				ts = ast_get_indication_tone(chan->zone, "busy");
+				break;
+			 case AST_CONTROL_CONGESTION:
+				ts = ast_get_indication_tone(chan->zone, "congestion");
+				break;
+			}
+			if (ts && ts->data[0]) {
+				ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition);
+				ast_playtones_start(chan,0,ts->data);
+			}
+			else  {
+				/* not handled */
+				ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
+				return -1;
+			}
+		}
+		else ast_playtones_stop(chan);
+	}
+	return 0;
 }
 
 int ast_recvchar(struct ast_channel *chan, int timeout)
@@ -1016,6 +1097,51 @@ int ast_sendtext(struct ast_channel *chan, char *text)
 	return res;
 }
 
+static int do_senddigit(struct ast_channel *chan, char digit)
+{
+	int res = -1;
+
+	if (chan->pvt->send_digit)
+		res = chan->pvt->send_digit(chan, digit);
+	if (!chan->pvt->send_digit || res) {
+		/*
+		 * Device does not support DTMF tones, lets fake
+		 * it by doing our own generation. (PM2002)
+		 */
+		static const char* dtmf_tones[] = {
+			"!941+1336/50,!0/50",	/* 0 */
+			"!697+1209/50,!0/50",	/* 1 */
+			"!697+1336/50,!0/50",	/* 2 */
+			"!697+1477/50,!0/50",	/* 3 */
+			"!770+1209/50,!0/50",	/* 4 */
+			"!770+1336/50,!0/50",	/* 5 */
+			"!770+1477/50,!0/50",	/* 6 */
+			"!852+1209/50,!0/50",	/* 7 */
+			"!852+1336/50,!0/50",	/* 8 */
+			"!852+1477/50,!0/50",	/* 9 */
+			"!697+1633/50,!0/50",	/* A */
+			"!770+1633/50,!0/50",	/* B */
+			"!852+1633/50,!0/50",	/* C */
+			"!941+1633/50,!0/50",	/* D */
+			"!941+1209/50,!0/50",	/* * */
+			"!941+1477/50,!0/50" };	/* # */
+		if (digit >= '0' && digit <='9')
+			ast_playtones_start(chan,0,dtmf_tones[digit-'0']);
+		else if (digit >= 'A' && digit <= 'D')
+			ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10]);
+		else if (digit == '*')
+			ast_playtones_start(chan,0,dtmf_tones[14]);
+		else if (digit == '#')
+			ast_playtones_start(chan,0,dtmf_tones[15]);
+		else {
+			/* not handled */
+			ast_log(LOG_WARNING, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
+			return -1;
+		}
+	}
+	return 0;
+}
+
 int ast_write(struct ast_channel *chan, struct ast_frame *fr)
 {
 	int res = -1;
@@ -1045,8 +1171,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
 		ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
 		break;
 	case AST_FRAME_DTMF:
-		if (chan->pvt->send_digit)
-			res = chan->pvt->send_digit(chan, fr->subclass);
+		res = do_senddigit(chan,fr->subclass);
 		break;
 	case AST_FRAME_TEXT:
 		if (chan->pvt->send_text)
@@ -1068,6 +1193,8 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
 	/* Consider a write failure to force a soft hangup */
 	if (res < 0)
 		chan->_softhangup |= AST_SOFTHANGUP_DEV;
+	else
+		chan->fout++;
 	return res;
 }
 
@@ -1129,7 +1256,7 @@ int ast_set_read_format(struct ast_channel *chan, int fmts)
 	return 0;
 }
 
-struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int timeout, int *outstate)
+struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int timeout, int *outstate, char *callerid)
 {
 	int state = 0;
 	struct ast_channel *chan;
@@ -1138,6 +1265,8 @@ struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int
 	
 	chan = ast_request(type, format, data);
 	if (chan) {
+		if (callerid)
+			ast_set_callerid(chan, callerid, 1);
 		if (!ast_call(chan, data, 0)) {
 			while(timeout && (chan->_state != AST_STATE_UP)) {
 				res = ast_waitfor(chan, timeout);
@@ -1370,11 +1499,20 @@ int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clo
 	return 0;
 }
 
+void ast_change_name(struct ast_channel *chan, char *newname)
+{
+	char tmp[256];
+	strncpy(tmp, chan->name, 256);
+	strncpy(chan->name, newname, sizeof(chan->name) - 1);
+	manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\n", tmp, chan->name);
+}
+
 static int ast_do_masquerade(struct ast_channel *original)
 {
 	int x;
 	int res=0;
 	char *tmp;
+	void *tmpv;
 	struct ast_channel_pvt *p;
 	struct ast_channel *clone = original->masq;
 	int rformat = original->readformat;
@@ -1384,9 +1522,9 @@ static int ast_do_masquerade(struct ast_channel *original)
 	char masqn[100];
 	char zombn[100];
 	
-#if 0
+#if 1
 	ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
-		clone->name, clone->state, original->name, original->state);
+		clone->name, clone->_state, original->name, original->_state);
 #endif
 	/* XXX This is a seriously wacked out operation.  We're essentially putting the guts of
 	   the clone channel into the original channel.  Start by killing off the original
@@ -1456,6 +1594,10 @@ static int ast_do_masquerade(struct ast_channel *original)
 	/* Copy the FD's */
 	for (x=0;x<AST_MAX_FDS;x++)
 		original->fds[x] = clone->fds[x];
+	/* Move the variables */
+	tmpv = original->varshead.first;
+	original->varshead.first = clone->varshead.first;
+	clone->varshead.first = tmpv;
 	/* Presense of ADSI capable CPE follows clone */
 	original->adsicpe = clone->adsicpe;
 	/* Bridge remains the same */
@@ -1482,6 +1624,11 @@ static int ast_do_masquerade(struct ast_channel *original)
 	
 	/* Our native formats are different now */
 	original->nativeformats = clone->nativeformats;
+
+	/* And of course, so does our current state.  Note we need not
+	   call ast_setstate since the event manager doesn't really consider
+	   these separate */
+	original->_state = clone->_state;
 	
 	/* Context, extension, priority, app data, jump table,  remain the same */
 	/* pvt switches.  pbx stays the same, as does next */
@@ -1492,6 +1639,7 @@ static int ast_do_masquerade(struct ast_channel *original)
 	if (clone->zombie) {
 		pthread_mutex_unlock(&clone->lock);
 		ast_channel_free(clone);
+		manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn);
 	} else {
 		clone->zombie=1;
 		pthread_mutex_unlock(&clone->lock);
@@ -1519,19 +1667,26 @@ static int ast_do_masquerade(struct ast_channel *original)
 	/* Signal any blocker */
 	if (original->blocking)
 		pthread_kill(original->blocker, SIGURG);
-	ast_log(LOG_DEBUG, "Done Masquerading %s(%d) into the structure of %s(%d)\n",
-		clone->name, clone->_state, original->name, original->_state);
 	return 0;
 }
 
-void ast_set_callerid(struct ast_channel *chan, char *callerid)
+void ast_set_callerid(struct ast_channel *chan, char *callerid, int anitoo)
 {
 	if (chan->callerid)
 		free(chan->callerid);
-	if (callerid)
+	if (anitoo && chan->ani)
+		free(chan->ani);
+	if (callerid) {
 		chan->callerid = strdup(callerid);
-	else
+		if (anitoo)
+			chan->ani = strdup(callerid);
+	} else {
 		chan->callerid = NULL;
+		if (anitoo)
+			chan->ani = NULL;
+	}
+	if (chan->cdr)
+		ast_cdr_setcid(chan->cdr, chan);
 	manager_event(EVENT_FLAG_CALL, "Newcallerid", 
 				"Channel: %s\r\n"
 				"Callerid: %s\r\n",
@@ -1571,6 +1726,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
 	struct ast_channel *who = NULL;
 	int res;
 	int nativefailed=0;
+
 	/* Stop if we're a zombie or need a soft hangup */
 	if (c0->zombie || ast_check_hangup(c0) || c1->zombie || ast_check_hangup(c1)) 
 		return -1;
@@ -1639,7 +1795,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
 		}
 		who = ast_waitfor_n(cs, 2, &to);
 		if (!who) {
-			ast_log(LOG_WARNING, "Nobody there??\n"); 
+			ast_log(LOG_DEBUG, "Nobody there, continuing...\n"); 
 			continue;
 		}
 		f = ast_read(who);
@@ -1649,6 +1805,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
 			res = 0;
 			break;
 		}
+
 		if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
 			*fo = f;
 			*rc = who;
@@ -1748,7 +1905,6 @@ struct tonepair_state {
 	float vol;
 	int duration;
 	int pos;
-	int origrfmt;
 	int origwfmt;
 	struct ast_frame f;
 	unsigned char offset[AST_FRIENDLY_OFFSET];
@@ -1760,7 +1916,6 @@ static void tonepair_release(struct ast_channel *chan, void *params)
 	struct tonepair_state *ts = params;
 	if (chan) {
 		ast_set_write_format(chan, ts->origwfmt);
-		ast_set_read_format(chan, ts->origrfmt);
 	}
 	free(ts);
 }
@@ -1773,17 +1928,11 @@ static void * tonepair_alloc(struct ast_channel *chan, void *params)
 	if (!ts)
 		return NULL;
 	memset(ts, 0, sizeof(struct tonepair_state));
-	ts->origrfmt = chan->readformat;
 	ts->origwfmt = chan->writeformat;
 	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
 		ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name);
 		tonepair_release(NULL, ts);
 		ts = NULL;
-	} else if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
-		ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (read)\n", chan->name);
-		ast_set_write_format(chan, ts->origwfmt);
-		tonepair_release(NULL, ts);
-		ts = NULL;
 	} else {
 		ts->freq1 = td->freq1;
 		ts->freq2 = td->freq2;
@@ -1795,10 +1944,16 @@ static void * tonepair_alloc(struct ast_channel *chan, void *params)
 	return ts;
 }
 
-static int tonepair_generator(struct ast_channel *chan, void *data, int len)
+static int tonepair_generator(struct ast_channel *chan, void *data, int len, int samples)
 {
 	struct tonepair_state *ts = data;
 	int x;
+
+	/* we need to prepare a frame with 16 * timelen samples as we're 
+	 * generating SLIN audio
+	 */
+	len = samples * 2;
+
 	if (len > sizeof(ts->data) / 2 - 1) {
 		ast_log(LOG_WARNING, "Can't generate that much data!\n");
 		return -1;
@@ -1813,7 +1968,7 @@ static int tonepair_generator(struct ast_channel *chan, void *data, int len)
 	ts->f.frametype = AST_FRAME_VOICE;
 	ts->f.subclass = AST_FORMAT_SLINEAR;
 	ts->f.datalen = len;
-	ts->f.timelen = len/8;
+	ts->f.samples = samples;
 	ts->f.offset = AST_FRIENDLY_OFFSET;
 	ts->f.data = ts->data;
 	ast_write(chan, &ts->f);
diff --git a/formats/format_mp3.c b/formats/format_mp3.c
index 5c730f098cd74fc11d80ed23cbc41939e3420eda..e702e556305f376daee5594618362aa2dd731ffd 100755
--- a/formats/format_mp3.c
+++ b/formats/format_mp3.c
@@ -192,7 +192,7 @@ static int ast_read_callback(void *data)
 			s->adj -= (ms - delay);
 		s->adj -= 2;
 	}
-	s->fr.timelen = delay;
+	s->fr.samples = delay * 8;
 #if 0
 	ast_log(LOG_DEBUG, "delay is %d, adjusting by %d, as last was %d\n", delay, s->adj, ms);
 #endif
@@ -218,6 +218,11 @@ static int mp3_apply(struct ast_channel *c, struct ast_filestream *s)
 {
 	/* Select our owner for this stream, and get the ball rolling. */
 	s->owner = c;
+	return 0;
+}
+
+static int mp3_play(struct ast_filestream *s)
+{
 	ast_read_callback(s);
 	return 0;
 }
@@ -240,6 +245,21 @@ static int mp3_write(struct ast_filestream *fs, struct ast_frame *f)
 	return 0;
 }
 
+static int mp3_seek(struct ast_filestream *fs, long sample_offset, int whence)
+{
+	return -1;
+}
+
+static int mp3_trunc(struct ast_filestream *fs)
+{
+	return -1;
+}
+
+static long mp3_tell(struct ast_filestream *fs)
+{
+	return -1;
+}
+
 static char *mp3_getcomment(struct ast_filestream *s)
 {
 	return NULL;
@@ -251,7 +271,11 @@ int load_module()
 								mp3_open,
 								mp3_rewrite,
 								mp3_apply,
+								mp3_play,
 								mp3_write,
+								mp3_seek,
+								mp3_trunc,
+								mp3_tell,
 								mp3_read,
 								mp3_close,
 								mp3_getcomment);