diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h
index 3df9001b0c..13410a00ae 100644
--- a/src/include/private/switch_core_pvt.h
+++ b/src/include/private/switch_core_pvt.h
@@ -135,6 +135,7 @@ struct switch_core_session {
 	switch_mutex_t *frame_read_mutex;
 
 	switch_thread_rwlock_t *rwlock;
+	switch_thread_rwlock_t *io_rwlock;
 
 	void *streams[SWITCH_MAX_STREAMS];
 	int stream_count;
diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index 33df7e31dd..840a06c204 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -354,6 +354,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void);
 ///\ingroup core1
 ///\{
 
+
+SWITCH_DECLARE(switch_status_t) switch_core_session_io_read_lock(switch_core_session_t *session);
+SWITCH_DECLARE(switch_status_t) switch_core_session_io_write_lock(switch_core_session_t *session);
+SWITCH_DECLARE(switch_status_t) switch_core_session_io_rwunlock(switch_core_session_t *session);
+
 #ifdef SWITCH_DEBUG_RWLOCKS
 SWITCH_DECLARE(switch_status_t) switch_core_session_perform_read_lock(_In_ switch_core_session_t *session, const char *file, const char *func, int line);
 #endif
diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h
index 249ac63a58..d277bd030f 100644
--- a/src/include/switch_ivr.h
+++ b/src/include/switch_ivr.h
@@ -874,6 +874,11 @@ SWITCH_DECLARE(void) switch_ivr_dmachine_set_input_timeout_ms(switch_ivr_dmachin
 SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_clear_realm(switch_ivr_dmachine_t *dmachine, const char *realm);
 SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_set_realm(switch_ivr_dmachine_t *dmachine, const char *realm);
 
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_get_file_handle(switch_core_session_t *session, switch_file_handle_t **fh);
+SWITCH_DECLARE(switch_status_t) switch_ivr_release_file_handle(switch_core_session_t *session, switch_file_handle_t **fh);
+SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *session, const char *cmd, switch_file_handle_t *fhp);
+
 /** @} */
 
 SWITCH_END_EXTERN_C
diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c
index ba4b6d310d..c7edfd5420 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -3968,6 +3968,47 @@ SWITCH_STANDARD_API(uuid_getvar_function)
 	return SWITCH_STATUS_SUCCESS;
 }
 
+
+#define FILEMAN_SYNTAX "<uuid> <cmd>:<val>"
+SWITCH_STANDARD_API(uuid_fileman_function)
+{
+	switch_core_session_t *psession = NULL;
+	char *mycmd = NULL, *argv[4] = { 0 };
+	int argc = 0;
+
+	if (!zstr(cmd) && (mycmd = strdup(cmd))) {
+		argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+		if (argc >= 2 && !zstr(argv[0])) {
+			char *uuid = argv[0];
+			char *cmd = argv[1];
+
+			if ((psession = switch_core_session_locate(uuid))) {
+				switch_channel_t *channel;
+				switch_file_handle_t *fh = NULL;
+				
+				channel = switch_core_session_get_channel(psession);
+				
+				if (switch_ivr_get_file_handle(psession, &fh) == SWITCH_STATUS_SUCCESS) {
+					switch_ivr_process_fh(psession, cmd, fh);
+					switch_ivr_release_file_handle(psession, &fh);
+				}
+
+				switch_core_session_rwunlock(psession);
+
+			} else {
+				stream->write_function(stream, "-ERR No Such Channel!\n");
+			}
+			goto done;
+		}
+	}
+
+	stream->write_function(stream, "-USAGE: %s\n", GETVAR_SYNTAX);
+
+  done:
+	switch_safe_free(mycmd);
+	return SWITCH_STATUS_SUCCESS;
+}
+
 #define UUID_SEND_DTMF_SYNTAX "<uuid> <dtmf_data>"
 SWITCH_STANDARD_API(uuid_send_dtmf_function)
 {
@@ -4674,6 +4715,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
 	SWITCH_ADD_API(commands_api_interface, "uuid_display", "change display", uuid_display_function, DISPLAY_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "uuid_dump", "uuid_dump", uuid_dump_function, DUMP_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "uuid_exists", "see if a uuid exists", uuid_exists_function, EXISTS_SYNTAX);
+	SWITCH_ADD_API(commands_api_interface, "uuid_fileman", "uuid_fileman", uuid_fileman_function, FILEMAN_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "uuid_flush_dtmf", "Flush dtmf on a given uuid", uuid_flush_dtmf_function, "<uuid>");
 	SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "uuid_getvar", uuid_getvar_function, GETVAR_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX);
@@ -4785,6 +4827,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
 	switch_console_set_complete("add uuid_display ::console::list_uuid");
 	switch_console_set_complete("add uuid_dump ::console::list_uuid");
 	switch_console_set_complete("add uuid_exists ::console::list_uuid");
+	switch_console_set_complete("add uuid_fileman ::console::list_uuid");
 	switch_console_set_complete("add uuid_flush_dtmf ::console::list_uuid");
 	switch_console_set_complete("add uuid_getvar ::console::list_uuid");
 	switch_console_set_complete("add uuid_hold ::console::list_uuid");
diff --git a/src/switch_core_rwlock.c b/src/switch_core_rwlock.c
index 4285491dc1..57168d9a29 100644
--- a/src/switch_core_rwlock.c
+++ b/src/switch_core_rwlock.c
@@ -36,6 +36,46 @@
 #include "private/switch_core_pvt.h"
 
 
+SWITCH_DECLARE(switch_status_t) switch_core_session_io_read_lock(switch_core_session_t *session)
+{
+	switch_status_t status = SWITCH_STATUS_FALSE;
+
+	if (session->io_rwlock) {
+		if (switch_thread_rwlock_tryrdlock(session->io_rwlock) == SWITCH_STATUS_SUCCESS) {
+			status = SWITCH_STATUS_SUCCESS;
+		}
+	}
+
+	return status;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_core_session_io_write_lock(switch_core_session_t *session)
+{
+	switch_status_t status = SWITCH_STATUS_FALSE;
+
+	if (session->io_rwlock) {
+		switch_thread_rwlock_wrlock(session->io_rwlock);
+		status = SWITCH_STATUS_SUCCESS;
+	}
+
+	return status;
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_core_session_io_rwunlock(switch_core_session_t *session)
+{
+	switch_status_t status = SWITCH_STATUS_FALSE;
+
+	if (session->io_rwlock) {
+		switch_thread_rwlock_unlock(session->io_rwlock);
+		status = SWITCH_STATUS_SUCCESS;
+	}
+
+	return status;
+}
+
+
+
 #ifdef SWITCH_DEBUG_RWLOCKS
 SWITCH_DECLARE(switch_status_t) switch_core_session_perform_read_lock(switch_core_session_t *session, const char *file, const char *func, int line)
 #else
diff --git a/src/switch_core_session.c b/src/switch_core_session.c
index a84bfabaf0..fc7648155a 100644
--- a/src/switch_core_session.c
+++ b/src/switch_core_session.c
@@ -1667,6 +1667,7 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_
 	switch_thread_rwlock_create(&session->bug_rwlock, session->pool);
 	switch_thread_cond_create(&session->cond, session->pool);
 	switch_thread_rwlock_create(&session->rwlock, session->pool);
+	switch_thread_rwlock_create(&session->io_rwlock, session->pool);
 	switch_queue_create(&session->message_queue, SWITCH_MESSAGE_QUEUE_LEN, session->pool);
 	switch_queue_create(&session->event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool);
 	switch_queue_create(&session->private_event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool);
diff --git a/src/switch_cpp.cpp b/src/switch_cpp.cpp
index 469ae18c4b..40462db567 100644
--- a/src/switch_cpp.cpp
+++ b/src/switch_cpp.cpp
@@ -1269,120 +1269,7 @@ SWITCH_DECLARE(switch_status_t) CoreSession::process_callback_result(char *resul
 	this_check(SWITCH_STATUS_FALSE);
 	sanity_check(SWITCH_STATUS_FALSE);
 	
-    if (zstr(result)) {
-		return SWITCH_STATUS_SUCCESS;	
-    }
-
-	if (fhp) {
-		if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) {
-			return SWITCH_STATUS_FALSE;
-		}
-
-		if (!strncasecmp(result, "speed", 5)) {
-			char *p;
-		
-			if ((p = strchr(result, ':'))) {
-				p++;
-				if (*p == '+' || *p == '-') {
-					int step;
-					if (!(step = atoi(p))) {
-						step = 1;
-					}
-					fhp->speed += step;
-				} else {
-					int speed = atoi(p);
-					fhp->speed = speed;
-				}
-				return SWITCH_STATUS_SUCCESS;
-			}
-
-			return SWITCH_STATUS_FALSE;
-
-		} else if (!strncasecmp(result, "volume", 6)) {
-			char *p;
-			
-			if ((p = strchr(result, ':'))) {
-				p++;
-				if (*p == '+' || *p == '-') {
-					int step;
-					if (!(step = atoi(p))) {
-						step = 1;
-					}
-					fhp->vol += step;
-				} else {
-					int vol = atoi(p);
-					fhp->vol = vol;
-				}
-				return SWITCH_STATUS_SUCCESS;
-			}
-			
-			if (fhp->vol) {
-				switch_normalize_volume(fhp->vol);
-			}
-			
-			return SWITCH_STATUS_FALSE;
-		} else if (!strcasecmp(result, "pause")) {
-			if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)) {
-				switch_clear_flag(fhp, SWITCH_FILE_PAUSE);
-			} else {
-				switch_set_flag(fhp, SWITCH_FILE_PAUSE);
-			}
-			return SWITCH_STATUS_SUCCESS;
-		} else if (!strcasecmp(result, "stop")) {
-			return SWITCH_STATUS_FALSE;
-		} else if (!strcasecmp(result, "truncate")) {
-			switch_core_file_truncate(fhp, 0);
-		} else if (!strcasecmp(result, "restart")) {
-			unsigned int pos = 0;
-			fhp->speed = 0;
-			switch_core_file_seek(fhp, &pos, 0, SEEK_SET);
-			return SWITCH_STATUS_SUCCESS;
-		} else if (!strncasecmp(result, "seek", 4)) {
-			switch_codec_t *codec;
-			unsigned int samps = 0;
-			unsigned int pos = 0;
-			char *p;
-			codec = switch_core_session_get_read_codec(session);
-			
-			if ((p = strchr(result, ':'))) {
-				p++;
-				if (*p == '+' || *p == '-') {
-					int step;
-					int32_t target;
-					if (!(step = atoi(p))) {
-						step = 1000;
-					}
-
-					samps = step * (codec->implementation->samples_per_second / 1000);
-					target = (int32_t)fhp->pos + samps;
-
-					if (target < 0) {
-						target = 0;
-					}
-
-					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target);
-					switch_core_file_seek(fhp, &pos, target, SEEK_SET);
-
-				} else {
-					samps = atoi(p) * (codec->implementation->samples_per_second / 1000);
-					if (samps < 0) {
-						samps = 0;
-					}
-					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps);
-					switch_core_file_seek(fhp, &pos, samps, SEEK_SET);
-				}
-			}
-
-			return SWITCH_STATUS_SUCCESS;
-		}
-	}
-
-    if (!strcmp(result, "true") || !strcmp(result, "undefined")) {
-		return SWITCH_STATUS_SUCCESS;
-    }
-
-
-    return SWITCH_STATUS_FALSE;
+	return switch_ivr_process_fh(session, result, fhp);
 }
 
 /* For Emacs:
diff --git a/src/switch_ivr.c b/src/switch_ivr.c
index df88451a3d..00917adc34 100644
--- a/src/switch_ivr.c
+++ b/src/switch_ivr.c
@@ -2563,6 +2563,124 @@ SWITCH_DECLARE(switch_bool_t) switch_ivr_uuid_exists(const char *uuid)
 	return exists;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *session, const char *cmd, switch_file_handle_t *fhp)
+{
+    if (zstr(cmd)) {
+		return SWITCH_STATUS_SUCCESS;	
+    }
+
+	if (fhp) {
+		if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) {
+			return SWITCH_STATUS_FALSE;
+		}
+
+		if (!strncasecmp(cmd, "speed", 5)) {
+			char *p;
+		
+			if ((p = strchr(cmd, ':'))) {
+				p++;
+				if (*p == '+' || *p == '-') {
+					int step;
+					if (!(step = atoi(p))) {
+						step = 1;
+					}
+					fhp->speed += step;
+				} else {
+					int speed = atoi(p);
+					fhp->speed = speed;
+				}
+				return SWITCH_STATUS_SUCCESS;
+			}
+
+			return SWITCH_STATUS_FALSE;
+
+		} else if (!strncasecmp(cmd, "volume", 6)) {
+			char *p;
+			
+			if ((p = strchr(cmd, ':'))) {
+				p++;
+				if (*p == '+' || *p == '-') {
+					int step;
+					if (!(step = atoi(p))) {
+						step = 1;
+					}
+					fhp->vol += step;
+				} else {
+					int vol = atoi(p);
+					fhp->vol = vol;
+				}
+				return SWITCH_STATUS_SUCCESS;
+			}
+			
+			if (fhp->vol) {
+				switch_normalize_volume(fhp->vol);
+			}
+			
+			return SWITCH_STATUS_FALSE;
+		} else if (!strcasecmp(cmd, "pause")) {
+			if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)) {
+				switch_clear_flag(fhp, SWITCH_FILE_PAUSE);
+			} else {
+				switch_set_flag(fhp, SWITCH_FILE_PAUSE);
+			}
+			return SWITCH_STATUS_SUCCESS;
+		} else if (!strcasecmp(cmd, "stop")) {
+			return SWITCH_STATUS_FALSE;
+		} else if (!strcasecmp(cmd, "truncate")) {
+			switch_core_file_truncate(fhp, 0);
+		} else if (!strcasecmp(cmd, "restart")) {
+			unsigned int pos = 0;
+			fhp->speed = 0;
+			switch_core_file_seek(fhp, &pos, 0, SEEK_SET);
+			return SWITCH_STATUS_SUCCESS;
+		} else if (!strncasecmp(cmd, "seek", 4)) {
+			switch_codec_t *codec;
+			unsigned int samps = 0;
+			unsigned int pos = 0;
+			char *p;
+			codec = switch_core_session_get_read_codec(session);
+			
+			if ((p = strchr(cmd, ':'))) {
+				p++;
+				if (*p == '+' || *p == '-') {
+					int step;
+					int32_t target;
+					if (!(step = atoi(p))) {
+						step = 1000;
+					}
+
+					samps = step * (codec->implementation->samples_per_second / 1000);
+					target = (int32_t)fhp->pos + samps;
+
+					if (target < 0) {
+						target = 0;
+					}
+
+					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target);
+					switch_core_file_seek(fhp, &pos, target, SEEK_SET);
+
+				} else {
+					samps = atoi(p) * (codec->implementation->samples_per_second / 1000);
+					if (samps < 0) {
+						samps = 0;
+					}
+					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps);
+					switch_core_file_seek(fhp, &pos, samps, SEEK_SET);
+				}
+			}
+
+			return SWITCH_STATUS_SUCCESS;
+		}
+	}
+
+    if (!strcmp(cmd, "true") || !strcmp(cmd, "undefined")) {
+		return SWITCH_STATUS_SUCCESS;
+    }
+
+    return SWITCH_STATUS_FALSE;
+	
+}
+
 
 /* For Emacs:
  * Local Variables:
diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c
index 7285b894ea..3c8fa5e10f 100644
--- a/src/switch_ivr_play_say.c
+++ b/src/switch_ivr_play_say.c
@@ -913,6 +913,31 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi
 	return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_ivr_get_file_handle(switch_core_session_t *session, switch_file_handle_t **fh)
+{
+	switch_file_handle_t *fhp;
+	switch_channel_t *channel = switch_core_session_get_channel(session);
+
+	*fh = NULL;
+	switch_core_session_io_read_lock(session);
+	
+	if ((fhp = switch_channel_get_private(channel, "__fh"))) {
+		*fh = fhp;
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	switch_core_session_io_rwunlock(session);
+
+	return SWITCH_STATUS_FALSE;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_release_file_handle(switch_core_session_t *session, switch_file_handle_t **fh)
+{
+	*fh = NULL;
+	switch_core_session_io_rwunlock(session);
+
+	return SWITCH_STATUS_SUCCESS;
+}
 
 #define FILE_STARTSAMPLES 1024 * 32
 #define FILE_BLOCKSIZE 1024 * 8
@@ -994,6 +1019,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
 	}
 
 
+
+
 	if (play_delimiter) {
 		file_dup = switch_core_session_strdup(session, file);
 		argc = switch_separate_string(file_dup, play_delimiter, argv, (sizeof(argv) / sizeof(argv[0])));
@@ -1134,6 +1161,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
 			status = SWITCH_STATUS_NOTFOUND;
 			continue;
 		}
+
+		switch_core_session_io_write_lock(session);
+		switch_channel_set_private(channel, "__fh", fh);
+		switch_core_session_io_rwunlock(session);
+
 		if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
 			asis = 1;
 		}
@@ -1208,7 +1240,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
 				} else {
 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
 									  "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
+					switch_core_session_io_write_lock(session);
+					switch_channel_set_private(channel, "__fh", NULL);
+					switch_core_session_io_rwunlock(session);
+
 					switch_core_file_close(fh);
+
 					switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE);
 					status = SWITCH_STATUS_GENERR;
 					continue;
@@ -1228,6 +1265,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
 			if (switch_core_timer_init(&timer, timer_name, interval, samples, pool) != SWITCH_STATUS_SUCCESS) {
 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Setup timer failed!\n");
 				switch_core_codec_destroy(&codec);
+				switch_core_session_io_write_lock(session);
+				switch_channel_set_private(channel, "__fh", NULL);
+				switch_core_session_io_rwunlock(session);
 				switch_core_file_close(fh);
 				switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE);
 				status = SWITCH_STATUS_GENERR;
@@ -1538,6 +1578,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
 		}
 		switch_channel_set_variable_printf(channel, "playback_samples", "%d", fh->samples_out);
 
+		switch_core_session_io_write_lock(session);
+		switch_channel_set_private(channel, "__fh", NULL);
+		switch_core_session_io_rwunlock(session);
+
 		switch_core_file_close(fh);
 
 		if (fh->audio_buffer) {