diff --git a/apps/app_datetime.c b/apps/app_datetime.c
new file mode 100755
index 0000000000000000000000000000000000000000..97c1088f87ee94a297a85d134a4556d32f1a034e
--- /dev/null
+++ b/apps/app_datetime.c
@@ -0,0 +1,84 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Time of day - Report the time of day
+ * 
+ * Copyright (C) 1999, Mark Spencer
+ *
+ * Mark Spencer <markster@linux-support.net>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ */
+
+#include <asterisk/lock.h>
+#include <asterisk/file.h>
+#include <asterisk/logger.h>
+#include <asterisk/channel.h>
+#include <asterisk/pbx.h>
+#include <asterisk/module.h>
+#include <asterisk/say.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <pthread.h>
+
+
+static char *tdesc = "Date and Time";
+
+static char *app = "DateTime";
+
+static char *synopsis = "Say the date and time";
+
+static char *descrip = 
+"  DateTime():  Says the current date and time.  Returns -1 on hangup or 0\n"
+"otherwise.\n";
+
+STANDARD_LOCAL_USER;
+
+LOCAL_USER_DECL;
+
+static int datetime_exec(struct ast_channel *chan, void *data)
+{
+	int res=0;
+	time_t t;
+	struct localuser *u;
+	LOCAL_USER_ADD(u);
+	time(&t);
+	if (chan->_state != AST_STATE_UP)
+		res = ast_answer(chan);
+	if (!res)
+		res = ast_say_datetime(chan, t, "", chan->language);
+	LOCAL_USER_REMOVE(u);
+	return res;
+}
+
+int unload_module(void)
+{
+	STANDARD_HANGUP_LOCALUSERS;
+	return ast_unregister_application(app);
+}
+
+int load_module(void)
+{
+	return ast_register_application(app, datetime_exec, synopsis, descrip);
+}
+
+char *description(void)
+{
+	return tdesc;
+}
+
+int usecount(void)
+{
+	int res;
+	STANDARD_USECOUNT(res);
+	return res;
+}
+
+char *key()
+{
+	return ASTERISK_GPL_KEY;
+}
diff --git a/apps/app_milliwatt.c b/apps/app_milliwatt.c
index 2f162f24204bb1f371006e79ccc5db4886a3643c..b117441df6b5855b6f3d626dc0c7e99e0e6bc3f0 100755
--- a/apps/app_milliwatt.c
+++ b/apps/app_milliwatt.c
@@ -100,11 +100,10 @@ static int milliwatt_exec(struct ast_channel *chan, void *data)
 {
 
 	struct localuser *u;
-	struct ast_frame *f;
 	LOCAL_USER_ADD(u);
 	ast_set_write_format(chan, AST_FORMAT_ULAW);
 	ast_set_read_format(chan, AST_FORMAT_ULAW);
-	if (chan->state != AST_STATE_UP)
+	if (chan->_state != AST_STATE_UP)
 	{
 		ast_answer(chan);
 	}
diff --git a/apps/app_playback.c b/apps/app_playback.c
index 5ca2626608d1e7df40a979fa9980230e91552f77..346617377b572f654949b492369097108345952a 100755
--- a/apps/app_playback.c
+++ b/apps/app_playback.c
@@ -63,7 +63,7 @@ static int playback_exec(struct ast_channel *chan, void *data)
 	if (options && !strcasecmp(options, "noanswer"))
 		option_noanswer = 1;
 	LOCAL_USER_ADD(u);
-	if (chan->state != AST_STATE_UP) {
+	if (chan->_state != AST_STATE_UP) {
 		if (option_skip) {
 			/* At the user's option, skip if the line is not up */
 			LOCAL_USER_REMOVE(u);
@@ -77,8 +77,10 @@ static int playback_exec(struct ast_channel *chan, void *data)
 		res = ast_streamfile(chan, tmp, chan->language);
 		if (!res) 
 			res = ast_waitstream(chan, "");
-		else
+		else {
 			ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
+			res = 0;
+		}
 		ast_stopstream(chan);
 	}
 	LOCAL_USER_REMOVE(u);
diff --git a/apps/app_qcall.c b/apps/app_qcall.c
index 1a7887bb3dff1abeffbd9d1d0d059624b9fc1e92..5a1df9726219e1265f82ee12a3a58f6a40ede9de 100755
--- a/apps/app_qcall.c
+++ b/apps/app_qcall.c
@@ -247,7 +247,7 @@ time_t	t;
 		if (channel->ani) free(channel->ani);
 		channel->ani = NULL;
 	}
-	if (channel->state == AST_STATE_UP)
+	if (channel->_state == AST_STATE_UP)
 	if (debug) printf("@@@@ Autodial:Line is Up\n");
 	if (option_verbose > 2)
 	ast_verbose(VERBOSE_PREFIX_3 "Qcall waiting for answer on %s\n",
@@ -274,7 +274,7 @@ time_t	t;
 			if (f->subclass == AST_CONTROL_ANSWER)
 			   {
 				if (debug) printf("@@@@ qcall_do:Phone Answered\n");
-				if (channel->state == AST_STATE_UP)
+				if (channel->_state == AST_STATE_UP)
 				   {
 					unlink(fname);
 					if (option_verbose > 2)
diff --git a/apps/app_record.c b/apps/app_record.c
index 4ad4a15fd575ee0d781ee5dea235f30d5e934300..1e54276b8bae79c9c166379c6ec0983229552193 100755
--- a/apps/app_record.c
+++ b/apps/app_record.c
@@ -95,7 +95,7 @@ static int record_exec(struct ast_channel *chan, void *data)
 
 	LOCAL_USER_ADD(u);
 
-	if (chan->state != AST_STATE_UP) {
+	if (chan->_state != AST_STATE_UP) {
 		res = ast_answer(chan); /* Shouldn't need this, but checking to see if channel is already answered
 					 * Theoretically asterisk should already have answered before running the app */
 	}
diff --git a/apps/app_zapateller.c b/apps/app_zapateller.c
index 658fde540abb85fd511328c2fa766f94416d7859..c9e5fdc34995aa96636a230814337b02a2707c78 100755
--- a/apps/app_zapateller.c
+++ b/apps/app_zapateller.c
@@ -45,7 +45,7 @@ static int zapateller_exec(struct ast_channel *chan, void *data)
 	
 	LOCAL_USER_ADD(u);
 	ast_stopstream(chan);
-	if (chan->state != AST_STATE_UP) {
+	if (chan->_state != AST_STATE_UP) {
 		if (data && !strcasecmp(data, "answer")) 
 			res = ast_answer(chan);
 		if (!res) {
diff --git a/apps/app_zapras.c b/apps/app_zapras.c
index 82614f120f2ce24ac389ec2076fad882ed3b4b85..7d2b0b83a01e4f80cd5c149254a764ae54e405b9 100755
--- a/apps/app_zapras.c
+++ b/apps/app_zapras.c
@@ -125,7 +125,7 @@ static void run_ras(struct ast_channel *chan, char *args)
 			res = wait4(pid, &status, WNOHANG, NULL);
 			if (!res) {
 				/* Check for hangup */
-				if (chan->softhangup && !signalled) {
+				if (chan->_softhangup && !signalled) {
 					ast_log(LOG_DEBUG, "Channel '%s' hungup.  Signalling RAS at %d to die...\n", chan->name, pid);
 					kill(pid, SIGTERM);
 					signalled=1;
@@ -182,7 +182,7 @@ static int zapras_exec(struct ast_channel *chan, void *data)
 	LOCAL_USER_ADD(u);
 	strncpy(args, data, sizeof(args) - 1);
 	/* Answer the channel if it's not up */
-	if (chan->state != AST_STATE_UP)
+	if (chan->_state != AST_STATE_UP)
 		ast_answer(chan);
 	if (strcasecmp(chan->type, "Zap")) {
 		/* If it's not a zap channel, we're done.  Wait a couple of
diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c
index be760b8bd5fe030150ae4d455234a78dbd06cfed..3e35a821fc538dd3c120db490d1f9696b515172e 100755
--- a/channels/chan_alsa.c
+++ b/channels/chan_alsa.c
@@ -506,7 +506,7 @@ static int alsa_answer(struct ast_channel *c)
 {
 	ast_verbose( " << Console call has been answered >> \n");
 	answer_sound();
-	c->state = AST_STATE_UP;
+	ast_setstate(c, AST_STATE_UP);
 	cursound = -1;
 	return 0;
 }
@@ -684,7 +684,7 @@ static struct ast_frame *alsa_read(struct ast_channel *chan)
 		needanswer = 0;
 		f.frametype = AST_FRAME_CONTROL;
 		f.subclass = AST_CONTROL_ANSWER;
-		chan->state = AST_STATE_UP;
+		ast_setstate(chan, AST_STATE_UP);
 		return &f;
 	}
 	
@@ -722,7 +722,7 @@ static struct ast_frame *alsa_read(struct ast_channel *chan)
 		/* A real frame */
 		readpos = 0;
 		left = FRAME_SIZE;
-		if (chan->state != AST_STATE_UP) {
+		if (chan->_state != AST_STATE_UP) {
 			/* Don't transmit unless it's up */
 			return &f;
 		}
@@ -806,7 +806,7 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state)
 		if (strlen(language))
 			strncpy(tmp->language, language, sizeof(tmp->language)-1);
 		p->owner = tmp;
-		tmp->state = state;
+		ast_setstate(tmp, state);
 		ast_pthread_mutex_lock(&usecnt_lock);
 		usecnt++;
 		ast_pthread_mutex_unlock(&usecnt_lock);
@@ -1087,7 +1087,7 @@ int unload_module()
 		close(sndcmd[1]);
 	}
 	if (alsa.owner)
-		ast_softhangup(alsa.owner);
+		ast_softhangup(alsa.owner, AST_SOFTHANGUP_APPUNLOAD);
 	if (alsa.owner)
 		return -1;
 	return 0;
diff --git a/channels/chan_modem.c b/channels/chan_modem.c
index 09c58c22c2bdec9d68112c3a0057978c472108ea..758235b4abd8b143f21c1ef0ea03f89340f1e087 100755
--- a/channels/chan_modem.c
+++ b/channels/chan_modem.c
@@ -177,7 +177,7 @@ static int modem_call(struct ast_channel *ast, char *idest, int timeout)
 	strcpy(dstr,where + p->stripmsd);
 	/* if not a transfer or just sending tones, must be in correct state */
 	if (strcasecmp(rdest, "transfer") && strcasecmp(rdest,"sendtones")) {
-		if ((ast->state != AST_STATE_DOWN) && (ast->state != AST_STATE_RESERVED)) {
+		if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
 			ast_log(LOG_WARNING, "modem_call called on %s, neither down nor reserved\n", ast->name);
 			return -1;
 		}
@@ -191,15 +191,15 @@ static int modem_call(struct ast_channel *ast, char *idest, int timeout)
 			if (p->mc->setdev(p, MODEM_DEV_HANDSET))
 				return -1;
 		/* Should be immediately up */
-		ast->state = AST_STATE_UP;
+		ast_setstate(ast, AST_STATE_UP);
 	} else {
 		if (p->mc->setdev)
 			if (p->mc->setdev(p, MODEM_DEV_TELCO_SPK))
 				return -1;
 		if (p->mc->dial)
 			p->mc->dial(p, dstr);
-		ast->state = AST_STATE_DIALING;
-		while((ast->state != AST_STATE_UP) && (ms > 0)) {
+		ast_setstate(ast, AST_STATE_DIALING);
+		while((ast->_state != AST_STATE_UP) && (ms > 0)) {
 			ms = ast_waitfor(ast, ms);
 			/* Just read packets and watch what happens */
 			if (ms > 0) {
@@ -410,7 +410,7 @@ static int modem_hangup(struct ast_channel *ast)
 	/* Re-initialize */
 	if (p->mc->init)
 		p->mc->init(p);
-	ast->state = AST_STATE_DOWN;
+	ast_setstate(ast, AST_STATE_DOWN);
 	memset(p->cid, 0, sizeof(p->cid));
 	memset(p->dnid, 0, sizeof(p->dnid));
 	((struct ast_modem_pvt *)(ast->pvt->pvt))->owner = NULL;
@@ -423,7 +423,7 @@ static int modem_hangup(struct ast_channel *ast)
 	if (option_verbose > 2) 
 		ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
 	ast->pvt->pvt = NULL;
-	ast->state = AST_STATE_DOWN;
+	ast_setstate(ast, AST_STATE_DOWN);
 	restart_monitor();
 	return 0;
 }
@@ -440,7 +440,7 @@ static int modem_answer(struct ast_channel *ast)
 	}
 	if (!res) {
 		ast->rings = 0;
-		ast->state = AST_STATE_UP;
+		ast_setstate(ast, AST_STATE_UP);
 	}
 	return res;
 }
@@ -494,7 +494,7 @@ struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
 		tmp->type = type;
 		tmp->fds[0] = i->fd;
 		tmp->nativeformats = i->mc->formats;
-		tmp->state = state;
+		ast_setstate(tmp, state);
 		if (state == AST_STATE_RING)
 			tmp->rings = 1;
 		tmp->pvt->pvt = i;
@@ -858,7 +858,7 @@ int unload_module()
 		p = iflist;
 		while(p) {
 			if (p->owner)
-				ast_softhangup(p->owner);
+				ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
 			p = p->next;
 		}
 		iflist = NULL;
diff --git a/channels/chan_modem_aopen.c b/channels/chan_modem_aopen.c
index b832f80923fa5badf6c8114ac3bcaafa64e1ddf1..b33ce074c2c5729356a84cac42cf128cac113c0c 100755
--- a/channels/chan_modem_aopen.c
+++ b/channels/chan_modem_aopen.c
@@ -202,7 +202,7 @@ static struct ast_frame *aopen_handle_escape(struct ast_modem_pvt *p, char esc)
 		p->fr.frametype = AST_FRAME_CONTROL;
 		p->fr.subclass = AST_CONTROL_RING;
 		if (p->owner)
-			p->owner->state = AST_STATE_UP;
+			ast_setstate(p->owner, AST_STATE_UP);
 		if (aopen_startrec(p))
 			return 	NULL;
 		return &p->fr;
diff --git a/channels/chan_modem_bestdata.c b/channels/chan_modem_bestdata.c
index b9f56d3b1915903324f263aa73b44fa87b1b5d06..08a1c2e89fb5c6a59f938b85c2144eb8ab627be3 100755
--- a/channels/chan_modem_bestdata.c
+++ b/channels/chan_modem_bestdata.c
@@ -208,7 +208,7 @@ static struct ast_frame *bestdata_handle_escape(struct ast_modem_pvt *p, char es
 		return &p->fr;
 	case '@': /* response from "OK" in command mode */
 		if (p->owner)
-			p->owner->state = AST_STATE_UP;
+			ast_setstate(p->owner, AST_STATE_UP);
 		if (bestdata_startrec(p)) return NULL;
 		p->fr.frametype = AST_FRAME_CONTROL;
 		p->fr.subclass = AST_CONTROL_RING;
@@ -386,7 +386,7 @@ short	*sp;
 unsigned long u;
 #define	DLE	16
 
-	if (p->owner && (p->owner->state == AST_STATE_UP) && 
+	if (p->owner && (p->owner->_state == AST_STATE_UP) && 
 		(p->ministate != STATE_VOICEPLAY) && bestdata_startplay(p)) return -1;
 	sp = (short *) f->data;
 	  /* stick DLE's in ahead of anything else */
diff --git a/channels/chan_modem_i4l.c b/channels/chan_modem_i4l.c
index 609fefffbd34176900f32d58932045b807fcb1c4..553f144ee5ffc0dd8dae1a32d57df4625ec33332 100755
--- a/channels/chan_modem_i4l.c
+++ b/channels/chan_modem_i4l.c
@@ -208,7 +208,7 @@ static struct ast_frame *i4l_handle_escape(struct ast_modem_pvt *p, char esc)
 		p->fr.frametype = AST_FRAME_CONTROL;
 		p->fr.subclass = AST_CONTROL_ANSWER;
 		if (p->owner)
-			p->owner->state = AST_STATE_UP;
+			ast_setstate(p->owner, AST_STATE_UP);
 		if (i4l_startrec(p))
 			return 	NULL;
 		return &p->fr;
diff --git a/include/asterisk/channel_pvt.h b/include/asterisk/channel_pvt.h
index 99515611f4a1cb99b0969cf0577bd247cbc01494..a96b4a13a6bce539a99f00b1bd06a2ab871bde28 100755
--- a/include/asterisk/channel_pvt.h
+++ b/include/asterisk/channel_pvt.h
@@ -78,6 +78,9 @@ int ast_queue_hangup(struct ast_channel *chan, int lock);
 
 int ast_queue_control(struct ast_channel *chan, int control, int lock);
 
+/*! Change the state of a channel */
+int ast_setstate(struct ast_channel *chan, int state);
+
 //! Free a channel structure
 void  ast_channel_free(struct ast_channel *);
 
diff --git a/include/asterisk/vmodem.h b/include/asterisk/vmodem.h
index ab7274c2c4be8de23c0566242cbd1b71a10a3785..457606c16e8412e85c58e3be5255e8bdb573fcb9 100755
--- a/include/asterisk/vmodem.h
+++ b/include/asterisk/vmodem.h
@@ -16,6 +16,7 @@
 
 #include <asterisk/frame.h>
 #include <asterisk/channel.h>
+#include <asterisk/channel_pvt.h>
 
 #define CHAR_DLE		0x10
 #define CHAR_ETX		0x03
diff --git a/pbx/pbx_wilcalu.c b/pbx/pbx_wilcalu.c
index df1788831363a776dc1c85bd8987f0caf4d47c15..a125bd1020174541d7939eacf2b41b8ff83d8208 100755
--- a/pbx/pbx_wilcalu.c
+++ b/pbx/pbx_wilcalu.c
@@ -189,7 +189,7 @@ static void *dialstring(void *string){
 		free(string);
 		pthread_exit(NULL);
 	}
-	if(channel->state==AST_STATE_UP)
+	if(channel->_state==AST_STATE_UP)
 		printf("Autodial:Line is Up\n");
 	while(ms>0){
 		struct ast_frame *f;
@@ -202,7 +202,7 @@ static void *dialstring(void *string){
 		if(f->frametype==AST_FRAME_CONTROL){
 			if(f->subclass==AST_CONTROL_ANSWER){
 				printf("Autodial:Phone Answered\n");
-				if(channel->state==AST_STATE_UP){
+				if(channel->_state==AST_STATE_UP){
 					char res;
 					ast_streamfile(channel,filename,0);
 					// Press Five for snooze