[Freeswitch-svn] [commit] r13182 - in freeswitch/trunk: build conf/autoload_configs src src/mod/applications/mod_dptools src/mod/formats/mod_file_string

FreeSWITCH SVN anthm at freeswitch.org
Tue Apr 28 16:46:18 PDT 2009


Author: anthm
Date: Tue Apr 28 18:46:18 2009
New Revision: 13182

Log:
Stings of files 

method 1 high level (core most funcs that use switch_ivr_playback)

Delimiter is set by a var which also enables the parser 
<action application="set" data="playback_delimiter=!"/>
<action application="set" data="playback_sleep_val=500"/>
<action application="playback" data="/ram/sr8k.wav!/ram/swimp.wav"/>

method 2 low level (mod_file_string lower level code that uses direct file handles)

Delimiter is always !
<action application="playback" data="file_string:///ram/sr8k.wav!/ram/swimp.wav"/>



Added:
   freeswitch/trunk/src/mod/formats/mod_file_string/
   freeswitch/trunk/src/mod/formats/mod_file_string/Makefile
   freeswitch/trunk/src/mod/formats/mod_file_string/mod_file_string.2008.vcproj
   freeswitch/trunk/src/mod/formats/mod_file_string/mod_file_string.c
   freeswitch/trunk/src/mod/formats/mod_file_string/mod_file_string.vcproj
Modified:
   freeswitch/trunk/build/modules.conf.in
   freeswitch/trunk/conf/autoload_configs/modules.conf.xml
   freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
   freeswitch/trunk/src/switch_ivr_play_say.c

Modified: freeswitch/trunk/build/modules.conf.in
==============================================================================
--- freeswitch/trunk/build/modules.conf.in	(original)
+++ freeswitch/trunk/build/modules.conf.in	Tue Apr 28 18:46:18 2009
@@ -59,6 +59,7 @@
 #formats/mod_shout
 formats/mod_local_stream
 formats/mod_tone_stream
+formats/mod_file_string
 #languages/mod_python
 languages/mod_spidermonkey
 languages/mod_spidermonkey_teletone

Modified: freeswitch/trunk/conf/autoload_configs/modules.conf.xml
==============================================================================
--- freeswitch/trunk/conf/autoload_configs/modules.conf.xml	(original)
+++ freeswitch/trunk/conf/autoload_configs/modules.conf.xml	Tue Apr 28 18:46:18 2009
@@ -79,6 +79,7 @@
     <!--For local streams (play all the files in a directory)-->
     <load module="mod_local_stream"/>
     <load module="mod_tone_stream"/>
+    <load module="mod_file_string"/>
 
     <!-- Timers -->
 

Modified: freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c	Tue Apr 28 18:46:18 2009
@@ -40,8 +40,6 @@
 SWITCH_STANDARD_DIALPLAN(inline_dialplan_hunt)
 {
 	switch_caller_extension_t *extension = NULL;
-	char *argv[128] = { 0 };
-	int argc;
 	switch_channel_t *channel = switch_core_session_get_channel(session);
 	int x = 0;
 	char *lbuf;
@@ -1834,7 +1832,7 @@
 {
 	switch_input_args_t args = { 0 };
 	switch_channel_t *channel = switch_core_session_get_channel(session);
-	switch_status_t status;
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
 
 	args.input_callback = on_dtmf;
 

Added: freeswitch/trunk/src/mod/formats/mod_file_string/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/formats/mod_file_string/Makefile	Tue Apr 28 18:46:18 2009
@@ -0,0 +1,2 @@
+BASE=../../../..
+include $(BASE)/build/modmake.rules

Added: freeswitch/trunk/src/mod/formats/mod_file_string/mod_file_string.2008.vcproj
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/formats/mod_file_string/mod_file_string.2008.vcproj	Tue Apr 28 18:46:18 2009
@@ -0,0 +1,283 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="mod_file_string"
+	ProjectGUID="{2CA40887-1622-46A1-A7F9-17FD7E7E545B}"
+	RootNamespace="mod_file_string"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="2"
+			InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				UsePrecompiledHeader="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			ConfigurationType="2"
+			InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				UsePrecompiledHeader="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="2"
+			InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				UsePrecompiledHeader="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			ConfigurationType="2"
+			InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				UsePrecompiledHeader="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath=".\mod_file_string.c"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

Added: freeswitch/trunk/src/mod/formats/mod_file_string/mod_file_string.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/formats/mod_file_string/mod_file_string.c	Tue Apr 28 18:46:18 2009
@@ -0,0 +1,188 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2009, Anthony Minessale II <anthm at freeswitch.org>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthm at freeswitch.org>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthm at freeswitch.org>
+ * Cesar Cepeda <cesar at auronix.com>
+ *
+ *
+ * mod_file_string.c -- Local Streaming Audio
+ *
+ */
+#include <switch.h>
+/* for apr_pstrcat */
+#define DEFAULT_PREBUFFER_SIZE 1024 * 64
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_file_string_load);
+
+SWITCH_MODULE_DEFINITION(mod_file_string, mod_file_string_load, NULL, NULL);
+
+
+struct file_string_source;
+
+static struct {
+	switch_mutex_t *mutex;
+	switch_hash_t *source_hash;
+} globals;
+
+struct file_string_context {
+	char *argv[128];
+	int argc;
+	int index;
+	int samples;
+	switch_file_handle_t fh;
+};
+
+typedef struct file_string_context file_string_context_t;
+
+
+static int next_file(switch_file_handle_t *handle)
+{
+	file_string_context_t *context = handle->private_info;
+
+	context->index++;
+	
+	if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) {
+		switch_core_file_close(&context->fh);
+	}
+
+	if (context->index == context->argc) {
+		return 0;
+	}
+
+	if (switch_core_file_open(&context->fh,
+							  context->argv[context->index],
+							  handle->channels,
+							  handle->samplerate,
+							  SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
+		return 0;
+	}
+	
+	handle->samples = context->fh.samples;
+	handle->samplerate = context->fh.samplerate;
+	handle->channels = context->fh.channels;
+	handle->format = context->fh.format;
+	handle->sections = context->fh.sections;
+	handle->seekable = context->fh.seekable;
+	handle->speed = context->fh.speed;
+	handle->interval = context->fh.interval;
+	
+	if (context->index == 0) {
+		context->samples = (handle->samplerate / 1000) * 250;
+	}
+
+	return 1;
+}
+
+static switch_status_t file_string_file_open(switch_file_handle_t *handle, const char *path)
+{
+	file_string_context_t *context;
+	char *file_dup;
+
+	if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "This format does not support writing!\n");
+		return SWITCH_STATUS_FALSE;
+	}
+	
+	context = switch_core_alloc(handle->memory_pool, sizeof(*context));
+	
+	file_dup = switch_core_strdup(handle->memory_pool, path);
+	context->argc = switch_separate_string(file_dup, '!', context->argv, (sizeof(context->argv) / sizeof(context->argv[0])));
+	context->index = -1;
+	
+	handle->private_info = context;
+	
+	return next_file(handle) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t file_string_file_close(switch_file_handle_t *handle)
+{
+	file_string_context_t *context = handle->private_info;
+
+	switch_core_file_close(&context->fh);
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t file_string_file_read(switch_file_handle_t *handle, void *data, size_t *len)
+{
+	file_string_context_t *context = handle->private_info;
+	switch_status_t status;
+	size_t llen = *len;
+
+	if (context->samples > 0) {
+		if (*len > (size_t)context->samples) {
+			*len = context->samples;
+		}
+		
+		context->samples -= *len;
+		switch_generate_sln_silence((int16_t *) data, *len, 400);
+		status = SWITCH_STATUS_SUCCESS;
+	} else {
+		status = switch_core_file_read(&context->fh, data, len);
+	}
+	
+	if (status != SWITCH_STATUS_SUCCESS) {
+		if (!next_file(handle)) {
+			return SWITCH_STATUS_FALSE;
+		}
+		*len = llen;
+		status = switch_core_file_read(&context->fh, data, len);
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+/* Registration */
+
+static char *supported_formats[SWITCH_MAX_CODECS] = { 0 };
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_file_string_load)
+{
+	switch_file_interface_t *file_interface;
+	supported_formats[0] = "file_string";
+
+	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
+	file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
+	file_interface->interface_name = modname;
+	file_interface->extens = supported_formats;
+	file_interface->file_open = file_string_file_open;
+	file_interface->file_close = file_string_file_close;
+	file_interface->file_read = file_string_file_read;
+
+	memset(&globals, 0, sizeof(globals));
+	/* indicate that the module should continue to be loaded */
+	return SWITCH_STATUS_SUCCESS;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */

Added: freeswitch/trunk/src/mod/formats/mod_file_string/mod_file_string.vcproj
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/formats/mod_file_string/mod_file_string.vcproj	Tue Apr 28 18:46:18 2009
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="mod_file_string"
+	ProjectGUID="{2CA40887-1622-46A1-A7F9-17FD7E7E545B}"
+	RootNamespace="mod_file_string"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			ConfigurationType="2"
+			InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCCLCompilerTool"
+				UsePrecompiledHeader="0"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			ConfigurationType="2"
+			InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCCLCompilerTool"
+				UsePrecompiledHeader="0"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath=".\mod_file_string.c"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

Modified: freeswitch/trunk/src/switch_ivr_play_say.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_play_say.c	(original)
+++ freeswitch/trunk/src/switch_ivr_play_say.c	Tue Apr 28 18:46:18 2009
@@ -354,7 +354,7 @@
 		input = input->next;
 	}
 
-  done:
+ done:
 
 	if (hint_data) {
 		switch_event_destroy(&hint_data);
@@ -588,9 +588,9 @@
 
 		if (args && (args->input_callback || args->buf || args->buflen)) {
 			/*
-			   dtmf handler function you can hook up to be executed when a digit is dialed during playback 
-			   if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
-			 */
+			  dtmf handler function you can hook up to be executed when a digit is dialed during playback 
+			  if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
+			*/
 			if (switch_channel_has_dtmf(channel)) {
 				if (!args->input_callback && !args->buf) {
 					status = SWITCH_STATUS_BREAK;
@@ -769,9 +769,9 @@
 
 		if (args && (args->input_callback || args->buf || args->buflen)) {
 			/*
-			   dtmf handler function you can hook up to be executed when a digit is dialed during gentones 
-			   if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
-			 */
+			  dtmf handler function you can hook up to be executed when a digit is dialed during gentones 
+			  if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
+			*/
 			if (switch_channel_has_dtmf(channel)) {
 				if (!args->input_callback && !args->buf) {
 					status = SWITCH_STATUS_BREAK;
@@ -848,12 +848,34 @@
 	const char *timer_name;
 	const char *prebuf;
 	const char *alt = NULL;
+	const char *sleep_val;
+	const char *play_delimiter_val;
+	char play_delimiter = 0;
+	int sleep_val_i = 250;
 	int eof = 0;
 	switch_size_t bread = 0;
 	int l16 = 0;
     switch_codec_implementation_t read_impl = {0};
+	char *file_dup;
+	char *argv[128] = { 0 };
+	int argc;
+	int cur;
+	switch_status_t rst;
+
+	
     switch_core_session_get_read_impl(session, &read_impl);
 
+	if ((play_delimiter_val = switch_channel_get_variable(channel, "playback_delimiter"))) {
+		play_delimiter = *play_delimiter_val;
+
+		if ((sleep_val = switch_channel_get_variable(channel, "playback_sleep_val"))) {
+			int tmp = atoi(sleep_val);
+			if (tmp >= 0) {
+				sleep_val_i = tmp;
+			}
+		}
+	}
+
 	if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
 		return SWITCH_STATUS_FALSE;
 	}
@@ -862,489 +884,528 @@
 	timer_name = switch_channel_get_variable(channel, "timer_name");
 
 	if (switch_strlen_zero(file) || !switch_channel_media_ready(channel)) {
-		status = SWITCH_STATUS_FALSE;
-		goto end;
+		return SWITCH_STATUS_FALSE;
 	}
 
 	if (!strcasecmp(read_impl.iananame, "l16")) {
 		l16++;
 	}
 
-	if ((alt = strchr(file, ':'))) {
-		char *dup;
+	
+	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])));
+	} else {
+		argc = 1;
+		argv[0] = (char *)file;
+	}
 
-		if (!strncasecmp(file, "phrase:", 7)) {
-			char *arg = NULL;
-			const char *lang = switch_channel_get_variable(channel, "language");
-			alt = file + 7;
-			dup = switch_core_session_strdup(session, alt);
-
-			if (dup) {
-				if ((arg = strchr(dup, ':'))) {
-					*arg++ = '\0';
-				}
-				return switch_ivr_phrase_macro(session, dup, arg, lang, args);
-			} else {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Args\n");
-				return SWITCH_STATUS_FALSE;
+	for(cur = 0; switch_channel_ready(channel) && cur < argc; cur++) {
+		file = argv[cur];
+		asis = 0;
+		eof = 0;
+		
+		if (cur) {
+			fh->samples = sample_start = 0;
+			if (sleep_val_i) {
+				switch_ivr_sleep(session, sleep_val_i, SWITCH_FALSE, args);
 			}
-		} else if (!strncasecmp(file, "say:", 4)) {
-			char *engine = NULL, *voice = NULL, *text = NULL;
-			alt = file + 4;
-			dup = switch_core_session_strdup(session, alt);
-			engine = dup;
-
-			if (!switch_strlen_zero(engine)) {
-				if ((voice = strchr(engine, ':'))) {
-					*voice++ = '\0';
-					if (!switch_strlen_zero(voice) && (text = strchr(voice, ':'))) {
-						*text++ = '\0';
+		}
+		
+		status = SWITCH_STATUS_SUCCESS;
+
+		if ((alt = strchr(file, ':'))) {
+			char *dup;
+
+			if (!strncasecmp(file, "phrase:", 7)) {
+				char *arg = NULL;
+				const char *lang = switch_channel_get_variable(channel, "language");
+				alt = file + 7;
+				dup = switch_core_session_strdup(session, alt);
+
+				if (dup) {
+					if ((arg = strchr(dup, ':'))) {
+						*arg++ = '\0';
+					}
+					if ((rst = switch_ivr_phrase_macro(session, dup, arg, lang, args) != SWITCH_STATUS_SUCCESS)) {
+						return rst;
+					}
+					continue;
+				} else {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Args\n");
+					continue;
+				}
+			} else if (!strncasecmp(file, "say:", 4)) {
+				char *engine = NULL, *voice = NULL, *text = NULL;
+				alt = file + 4;
+				dup = switch_core_session_strdup(session, alt);
+				engine = dup;
+
+				if (!switch_strlen_zero(engine)) {
+					if ((voice = strchr(engine, ':'))) {
+						*voice++ = '\0';
+						if (!switch_strlen_zero(voice) && (text = strchr(voice, ':'))) {
+							*text++ = '\0';
+						}
 					}
 				}
-			}
 
-			if (!switch_strlen_zero(engine) && !switch_strlen_zero(voice) && !switch_strlen_zero(text)) {
-				return switch_ivr_speak_text(session, engine, voice, text, args);
-			} else if (!switch_strlen_zero(engine) && !(voice && text)) {
-				text = engine;
-				engine = (char *) switch_channel_get_variable(channel, "tts_engine");
-				voice = (char *) switch_channel_get_variable(channel, "tts_voice");
-				if (engine && text) {
-					return switch_ivr_speak_text(session, engine, voice, text, args);
+				if (!switch_strlen_zero(engine) && !switch_strlen_zero(voice) && !switch_strlen_zero(text)) {
+					if ((rst = switch_ivr_speak_text(session, engine, voice, text, args)) != SWITCH_STATUS_SUCCESS) {
+						return rst;
+					}
+					continue;
+				} else if (!switch_strlen_zero(engine) && !(voice && text)) {
+					text = engine;
+					engine = (char *) switch_channel_get_variable(channel, "tts_engine");
+					voice = (char *) switch_channel_get_variable(channel, "tts_voice");
+					if (engine && text) {
+						if ((rst = switch_ivr_speak_text(session, engine, voice, text, args)) != SWITCH_STATUS_SUCCESS) {
+							return rst;
+						}
+						continue;
+					}
+				} else {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Args\n");
+					continue;
 				}
+			}
+
+		}
+
+		if (!prefix) {
+			prefix = SWITCH_GLOBAL_dirs.base_dir;
+		}
+
+		if (!strstr(file, SWITCH_URL_SEPARATOR)) {
+			if (!switch_is_file_path(file)) {
+				file = switch_core_session_sprintf(session, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, file);
+			}
+			if ((ext = strrchr(file, '.'))) {
+				ext++;
 			} else {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Args\n");
-				return SWITCH_STATUS_FALSE;
+				ext = read_impl.iananame;
+				file = switch_core_session_sprintf(session, "%s.%s", file, ext);
+				asis = 1;
 			}
 		}
 
-	}
+	
+		if (!fh) {
+			fh = &lfh;
+			memset(fh, 0, sizeof(lfh));
+		}
 
-	if (!prefix) {
-		prefix = SWITCH_GLOBAL_dirs.base_dir;
-	}
+		if (fh->samples > 0) {
+			sample_start = fh->samples;
+			fh->samples = 0;
+		}
 
-	if (!strstr(file, SWITCH_URL_SEPARATOR)) {
-		if (!switch_is_file_path(file)) {
-			file = switch_core_session_sprintf(session, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, file);
+		if ((prebuf = switch_channel_get_variable(channel, "stream_prebuffer"))) {
+			int maybe = atoi(prebuf);
+			if (maybe > 0) {
+				fh->prebuf = maybe;
+			}
 		}
-		if ((ext = strrchr(file, '.'))) {
-			ext++;
-		} else {
-			ext = read_impl.iananame;
-			file = switch_core_session_sprintf(session, "%s.%s", file, ext);
+		
+		if (switch_core_file_open(fh,
+								  file,
+								  read_impl.number_of_channels,
+								  read_impl.actual_samples_per_second,
+								  SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
+			switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
+			status = SWITCH_STATUS_NOTFOUND;
+			continue;
+		}
+		if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
 			asis = 1;
 		}
-	}
-
-	if (!fh) {
-		fh = &lfh;
-		memset(fh, 0, sizeof(lfh));
-	}
 
-	if (fh->samples > 0) {
-		sample_start = fh->samples;
-		fh->samples = 0;
-	}
+		if (!abuf) {
+			switch_zmalloc(abuf, FILE_STARTSAMPLES * sizeof(*abuf));
+			write_frame.data = abuf;
+			write_frame.buflen = FILE_STARTSAMPLES;
+		}
 
-	if ((prebuf = switch_channel_get_variable(channel, "stream_prebuffer"))) {
-		int maybe = atoi(prebuf);
-		if (maybe > 0) {
-			fh->prebuf = maybe;
+		if (sample_start > 0) {
+			uint32_t pos = 0;
+			switch_core_file_seek(fh, &pos, 0, SEEK_SET);
+			switch_core_file_seek(fh, &pos, sample_start, SEEK_CUR);
 		}
-	}
 
-	if (switch_core_file_open(fh,
-							  file,
-							  read_impl.number_of_channels,
-							  read_impl.actual_samples_per_second,
-							  SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
-		switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
-		status = SWITCH_STATUS_NOTFOUND;
-		goto end;
-	}
-	if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
-		asis = 1;
-	}
+		if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_TITLE, &p) == SWITCH_STATUS_SUCCESS) {
+			title = switch_core_session_strdup(session, p);
+			switch_channel_set_variable(channel, "RECORD_TITLE", p);
+		}
 
-	switch_zmalloc(abuf, FILE_STARTSAMPLES * sizeof(*abuf));
-	write_frame.data = abuf;
-	write_frame.buflen = FILE_STARTSAMPLES;
+		if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_COPYRIGHT, &p) == SWITCH_STATUS_SUCCESS) {
+			copyright = switch_core_session_strdup(session, p);
+			switch_channel_set_variable(channel, "RECORD_COPYRIGHT", p);
+		}
 
-	if (sample_start > 0) {
-		uint32_t pos = 0;
-		switch_core_file_seek(fh, &pos, 0, SEEK_SET);
-		switch_core_file_seek(fh, &pos, sample_start, SEEK_CUR);
-	}
+		if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_SOFTWARE, &p) == SWITCH_STATUS_SUCCESS) {
+			software = switch_core_session_strdup(session, p);
+			switch_channel_set_variable(channel, "RECORD_SOFTWARE", p);
+		}
 
-	if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_TITLE, &p) == SWITCH_STATUS_SUCCESS) {
-		title = switch_core_session_strdup(session, p);
-		switch_channel_set_variable(channel, "RECORD_TITLE", p);
-	}
+		if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_ARTIST, &p) == SWITCH_STATUS_SUCCESS) {
+			artist = switch_core_session_strdup(session, p);
+			switch_channel_set_variable(channel, "RECORD_ARTIST", p);
+		}
 
-	if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_COPYRIGHT, &p) == SWITCH_STATUS_SUCCESS) {
-		copyright = switch_core_session_strdup(session, p);
-		switch_channel_set_variable(channel, "RECORD_COPYRIGHT", p);
-	}
+		if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_COMMENT, &p) == SWITCH_STATUS_SUCCESS) {
+			comment = switch_core_session_strdup(session, p);
+			switch_channel_set_variable(channel, "RECORD_COMMENT", p);
+		}
 
-	if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_SOFTWARE, &p) == SWITCH_STATUS_SUCCESS) {
-		software = switch_core_session_strdup(session, p);
-		switch_channel_set_variable(channel, "RECORD_SOFTWARE", p);
-	}
+		if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_DATE, &p) == SWITCH_STATUS_SUCCESS) {
+			date = switch_core_session_strdup(session, p);
+			switch_channel_set_variable(channel, "RECORD_DATE", p);
+		}
 
-	if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_ARTIST, &p) == SWITCH_STATUS_SUCCESS) {
-		artist = switch_core_session_strdup(session, p);
-		switch_channel_set_variable(channel, "RECORD_ARTIST", p);
-	}
+		interval = read_impl.microseconds_per_packet / 1000;
 
-	if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_COMMENT, &p) == SWITCH_STATUS_SUCCESS) {
-		comment = switch_core_session_strdup(session, p);
-		switch_channel_set_variable(channel, "RECORD_COMMENT", p);
-	}
+		if (!fh->audio_buffer) {
+			switch_buffer_create_dynamic(&fh->audio_buffer, FILE_BLOCKSIZE, FILE_BUFSIZE, 0);
+			switch_assert(fh->audio_buffer);
+		}
 
-	if (switch_core_file_get_string(fh, SWITCH_AUDIO_COL_STR_DATE, &p) == SWITCH_STATUS_SUCCESS) {
-		date = switch_core_session_strdup(session, p);
-		switch_channel_set_variable(channel, "RECORD_DATE", p);
-	}
+		if (asis) {
+			write_frame.codec = switch_core_session_get_read_codec(session);
+			samples = read_impl.samples_per_packet;
+			framelen = read_impl.encoded_bytes_per_packet;
+		} else {
+			codec_name = "L16";
 
-	interval = read_impl.microseconds_per_packet / 1000;
+			if (!switch_core_codec_ready((&codec))) {
+				if (switch_core_codec_init(&codec,
+										   codec_name,
+										   NULL,
+										   fh->samplerate,
+										   interval, fh->channels, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, pool) == SWITCH_STATUS_SUCCESS) {
+					switch_log_printf(SWITCH_CHANNEL_LOG,
+									  SWITCH_LOG_DEBUG, "Codec Activated %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
+				
 
-	if (!fh->audio_buffer) {
-		switch_buffer_create_dynamic(&fh->audio_buffer, FILE_BLOCKSIZE, FILE_BUFSIZE, 0);
-		if (!fh->audio_buffer) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setup buffer failed\n");
+				} else {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
+									  "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
+					switch_core_file_close(fh);
+					switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
+					status = SWITCH_STATUS_GENERR;
+					continue;
+				}
+			}
 
-			switch_core_file_close(fh);
-			switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
+			write_frame.codec = &codec;
 
-			status = SWITCH_STATUS_GENERR;
-			goto end;
+			samples = codec.implementation->samples_per_packet;
+			framelen = codec.implementation->decoded_bytes_per_packet;
 		}
-	}
 
-	if (asis) {
-		write_frame.codec = switch_core_session_get_read_codec(session);
-		samples = read_impl.samples_per_packet;
-		framelen = read_impl.encoded_bytes_per_packet;
-	} else {
-		codec_name = "L16";
+		if (timer_name && !timer.samplecount) {
+			uint32_t len;
 
-		if (switch_core_codec_init(&codec,
-								   codec_name,
-								   NULL,
-								   fh->samplerate,
-								   interval, fh->channels, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, pool) == SWITCH_STATUS_SUCCESS) {
-			switch_log_printf(SWITCH_CHANNEL_LOG,
-							  SWITCH_LOG_DEBUG, "Codec Activated %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
+			len = samples * 2;
+			if (switch_core_timer_init(&timer, timer_name, interval, samples, pool) != SWITCH_STATUS_SUCCESS) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setup timer failed!\n");
+				switch_core_codec_destroy(&codec);
+				switch_core_file_close(fh);
+				switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
+				status = SWITCH_STATUS_GENERR;
+				continue;
+			}
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Setup timer success %u bytes per %d ms!\n", len, interval);
+		}
+		write_frame.rate = fh->samplerate;
 
-			write_frame.codec = &codec;
-		} else {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
-							  "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
-			switch_core_file_close(fh);
-			switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
-			status = SWITCH_STATUS_GENERR;
-			goto end;
+		if (timer_name) {
+			/* start a thread to absorb incoming audio */
+			switch_core_service_session(session);
 		}
-		samples = codec.implementation->samples_per_packet;
-		framelen = codec.implementation->decoded_bytes_per_packet;
-	}
 
-	if (timer_name) {
-		uint32_t len;
+		ilen = samples;
 
-		len = samples * 2;
-		if (switch_core_timer_init(&timer, timer_name, interval, samples, pool) != SWITCH_STATUS_SUCCESS) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setup timer failed!\n");
-			switch_core_codec_destroy(&codec);
-			switch_core_file_close(fh);
-			switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
-			status = SWITCH_STATUS_GENERR;
-			goto end;
-		}
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Setup timer success %u bytes per %d ms!\n", len, interval);
-	}
-	write_frame.rate = fh->samplerate;
+		for (;;) {
+			int done = 0;
+			int do_speed = 1;
+			int last_speed = -1;
 
-	if (timer_name) {
-		/* start a thread to absorb incoming audio */
-		switch_core_service_session(session);
-	}
+			if (!switch_channel_ready(channel)) {
+				status = SWITCH_STATUS_FALSE;
+				break; 
+			}
 
-	ilen = samples;
+			if (switch_channel_test_flag(channel, CF_BREAK)) {
+				switch_channel_clear_flag(channel, CF_BREAK);
+				status = SWITCH_STATUS_BREAK;
+				break; 
+			}
 
-	for (;;) {
-		int done = 0;
-		int do_speed = 1;
-		int last_speed = -1;
+			if (switch_core_session_private_event_count(session)) {
+				switch_ivr_parse_all_events(session);
+			}
 
-		if (!switch_channel_ready(channel)) {
-			status = SWITCH_STATUS_FALSE;
-			break; 
-		}
+			if (args && (args->input_callback || args->buf || args->buflen)) {
+				/*
+				  dtmf handler function you can hook up to be executed when a digit is dialed during playback 
+				  if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
+				*/
+				if (switch_channel_has_dtmf(channel)) {
+					if (!args->input_callback && !args->buf) {
+						status = SWITCH_STATUS_BREAK;
+						done = 1;
+						break; 
+					}
+					switch_channel_dequeue_dtmf(channel, &dtmf);
+					if (args->input_callback) {
+						status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
+					} else {
+						*((char *) args->buf) = dtmf.digit;
+						status = SWITCH_STATUS_BREAK;
+					}
+				}
 
-		if (switch_channel_test_flag(channel, CF_BREAK)) {
-			switch_channel_clear_flag(channel, CF_BREAK);
-			status = SWITCH_STATUS_BREAK;
-			break; 
-		}
+				if (args->input_callback) {
+					switch_event_t *event;
 
-		if (switch_core_session_private_event_count(session)) {
-			switch_ivr_parse_all_events(session);
-		}
+					if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
+						status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
+						switch_event_destroy(&event);
+					}
+				}
 
-		if (args && (args->input_callback || args->buf || args->buflen)) {
-			/*
-			   dtmf handler function you can hook up to be executed when a digit is dialed during playback 
-			   if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
-			 */
-			if (switch_channel_has_dtmf(channel)) {
-				if (!args->input_callback && !args->buf) {
-					status = SWITCH_STATUS_BREAK;
+				if (status != SWITCH_STATUS_SUCCESS) {
 					done = 1;
 					break; 
 				}
-				switch_channel_dequeue_dtmf(channel, &dtmf);
-				if (args->input_callback) {
-					status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
-				} else {
-					*((char *) args->buf) = dtmf.digit;
-					status = SWITCH_STATUS_BREAK;
-				}
 			}
 
-			if (args->input_callback) {
-				switch_event_t *event;
-
-				if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
-					status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen);
-					switch_event_destroy(&event);
+			if (switch_test_flag(fh, SWITCH_FILE_PAUSE)) {
+				if (framelen > FILE_STARTSAMPLES) {
+					framelen = FILE_STARTSAMPLES;
+				}
+				memset(abuf, 0, framelen);
+				olen = ilen;
+				do_speed = 0;
+			} else if (fh->sp_audio_buffer && (eof || (switch_buffer_inuse(fh->sp_audio_buffer) > (switch_size_t) (framelen)))) {
+				if (!(bread = switch_buffer_read(fh->sp_audio_buffer, abuf, framelen))) {
+					if (eof) {
+						continue;
+					} else {
+						break; 
+					}
 				}
-			}
 
-			if (status != SWITCH_STATUS_SUCCESS) {
-				done = 1;
-				break; 
-			}
-		}
+				if (bread < framelen) {
+					memset(abuf + bread, 0, framelen - bread);
+				}
 
-		if (switch_test_flag(fh, SWITCH_FILE_PAUSE)) {
-			if (framelen > FILE_STARTSAMPLES) {
-				framelen = FILE_STARTSAMPLES;
-			}
-			memset(abuf, 0, framelen);
-			olen = ilen;
-			do_speed = 0;
-		} else if (fh->sp_audio_buffer && (eof || (switch_buffer_inuse(fh->sp_audio_buffer) > (switch_size_t) (framelen)))) {
-			if (!(bread = switch_buffer_read(fh->sp_audio_buffer, abuf, framelen))) {
-				if (eof) {
-					continue;
-				} else {
-					break; 
+				olen = asis ? framelen : ilen;
+				do_speed = 0;
+			} else if (fh->audio_buffer && (eof || (switch_buffer_inuse(fh->audio_buffer) > (switch_size_t) (framelen)))) {
+				if (!(bread = switch_buffer_read(fh->audio_buffer, abuf, framelen))) {
+					if (eof) {
+						break; 
+					} else {
+						continue;
+					}
 				}
-			}
 
-			if (bread < framelen) {
-				memset(abuf + bread, 0, framelen - bread);
-			}
+				if (bread < framelen) {
+					memset(abuf + bread, 0, framelen - bread);
+				}
 
-			olen = asis ? framelen : ilen;
-			do_speed = 0;
-		} else if (fh->audio_buffer && (eof || (switch_buffer_inuse(fh->audio_buffer) > (switch_size_t) (framelen)))) {
-			if (!(bread = switch_buffer_read(fh->audio_buffer, abuf, framelen))) {
+				olen = asis ? framelen : ilen;
+			} else {
 				if (eof) {
-					break; 
-				} else {
+					break;
+				}
+				olen = FILE_STARTSAMPLES;
+				if (!asis) {
+					olen /= 2;
+				}
+				if (switch_core_file_read(fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
+					eof++;
 					continue;
 				}
+				switch_buffer_write(fh->audio_buffer, abuf, asis ? olen : olen * 2);
+				olen = switch_buffer_read(fh->audio_buffer, abuf, framelen);
+				if (!asis) {
+					olen /= 2;
+				}
 			}
 
-			if (bread < framelen) {
-				memset(abuf + bread, 0, framelen - bread);
+			if (done || olen <= 0) {
+				break; 
 			}
 
-			olen = asis ? framelen : ilen;
-		} else {
-			if (eof) {
-				break;
-			}
-			olen = FILE_STARTSAMPLES;
-			if (!asis) {
-				olen /= 2;
-			}
-			if (switch_core_file_read(fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
-				eof++;
-				continue;
-			}
-			switch_buffer_write(fh->audio_buffer, abuf, asis ? olen : olen * 2);
-			olen = switch_buffer_read(fh->audio_buffer, abuf, framelen);
 			if (!asis) {
-				olen /= 2;
+				if (fh->speed > 2) {
+					fh->speed = 2;
+				} else if (fh->speed < -2) {
+					fh->speed = -2;
+				}
 			}
-		}
 
-		if (done || olen <= 0) {
-			break; 
-		}
-
-		if (!asis) {
-			if (fh->speed > 2) {
-				fh->speed = 2;
-			} else if (fh->speed < -2) {
-				fh->speed = -2;
+			if (!asis && fh->audio_buffer && last_speed > -1 && last_speed != fh->speed) {
+				switch_buffer_zero(fh->sp_audio_buffer);
 			}
-		}
-
-		if (!asis && fh->audio_buffer && last_speed > -1 && last_speed != fh->speed) {
-			switch_buffer_zero(fh->sp_audio_buffer);
-		}
 
-		if (switch_test_flag(fh, SWITCH_FILE_SEEK)) {
-			/* file position has changed flush the buffer */
-			switch_buffer_zero(fh->audio_buffer);
-			switch_clear_flag(fh, SWITCH_FILE_SEEK);
-		}
+			if (switch_test_flag(fh, SWITCH_FILE_SEEK)) {
+				/* file position has changed flush the buffer */
+				switch_buffer_zero(fh->audio_buffer);
+				switch_clear_flag(fh, SWITCH_FILE_SEEK);
+			}
 
 
-		if (!asis && fh->speed && do_speed) {
-			float factor = 0.25f * abs(fh->speed);
-			switch_size_t newlen, supplement, step;
-			short *bp = write_frame.data;
-			switch_size_t wrote = 0;
+			if (!asis && fh->speed && do_speed) {
+				float factor = 0.25f * abs(fh->speed);
+				switch_size_t newlen, supplement, step;
+				short *bp = write_frame.data;
+				switch_size_t wrote = 0;
 
-			supplement = (int) (factor * olen);
-			if (!supplement) {
-				supplement = 1;
-			}
-			newlen = (fh->speed > 0) ? olen - supplement : olen + supplement;
+				supplement = (int) (factor * olen);
+				if (!supplement) {
+					supplement = 1;
+				}
+				newlen = (fh->speed > 0) ? olen - supplement : olen + supplement;
 
-			step = (fh->speed > 0) ? (newlen / supplement) : (olen / supplement);
+				step = (fh->speed > 0) ? (newlen / supplement) : (olen / supplement);
 
-			if (!fh->sp_audio_buffer) {
-				switch_buffer_create_dynamic(&fh->sp_audio_buffer, 1024, 1024, 0);
-			}
+				if (!fh->sp_audio_buffer) {
+					switch_buffer_create_dynamic(&fh->sp_audio_buffer, 1024, 1024, 0);
+				}
 
-			while ((wrote + step) < newlen) {
-				switch_buffer_write(fh->sp_audio_buffer, bp, step * 2);
-				wrote += step;
-				bp += step;
-				if (fh->speed > 0) {
-					bp++;
-				} else {
-					float f;
-					short s;
-					f = (float) (*bp + *(bp + 1) + *(bp - 1));
-					f /= 3;
-					s = (short) f;
-					switch_buffer_write(fh->sp_audio_buffer, &s, 2);
-					wrote++;
+				while ((wrote + step) < newlen) {
+					switch_buffer_write(fh->sp_audio_buffer, bp, step * 2);
+					wrote += step;
+					bp += step;
+					if (fh->speed > 0) {
+						bp++;
+					} else {
+						float f;
+						short s;
+						f = (float) (*bp + *(bp + 1) + *(bp - 1));
+						f /= 3;
+						s = (short) f;
+						switch_buffer_write(fh->sp_audio_buffer, &s, 2);
+						wrote++;
+					}
 				}
+				if (wrote < newlen) {
+					switch_size_t r = newlen - wrote;
+					switch_buffer_write(fh->sp_audio_buffer, bp, r * 2);
+					wrote += r;
+				}
+				last_speed = fh->speed;
+				continue;
 			}
-			if (wrote < newlen) {
-				switch_size_t r = newlen - wrote;
-				switch_buffer_write(fh->sp_audio_buffer, bp, r * 2);
-				wrote += r;
+
+			if (olen < llen) {
+				uint8_t *dp = (uint8_t *) write_frame.data;
+				memset(dp + (int) olen, 0, (int) (llen - olen));
+				olen = llen;
 			}
-			last_speed = fh->speed;
-			continue;
-		}
-		if (olen < llen) {
-			uint8_t *dp = (uint8_t *) write_frame.data;
-			memset(dp + (int) olen, 0, (int) (llen - olen));
-			olen = llen;
-		}
 
-		write_frame.samples = (uint32_t) olen;
+			write_frame.samples = (uint32_t) olen;
 
-		if (asis) {
-			write_frame.datalen = (uint32_t) olen;
-		} else {
-			write_frame.datalen = write_frame.samples * 2;
-		}
+			if (asis) {
+				write_frame.datalen = (uint32_t) olen;
+			} else {
+				write_frame.datalen = write_frame.samples * 2;
+			}
 
-		llen = olen;
+			llen = olen;
 
-		if (timer_name) {
-			write_frame.timestamp = timer.samplecount;
-		}
+			if (timer_name) {
+				write_frame.timestamp = timer.samplecount;
+			}
 #ifndef WIN32
 #if SWITCH_BYTE_ORDER == __BIG_ENDIAN
-		if (!asis && l16) {
-			switch_swap_linear(write_frame.data, (int) write_frame.datalen / 2);
-		}
+			if (!asis && l16) {
+				switch_swap_linear(write_frame.data, (int) write_frame.datalen / 2);
+			}
 #endif
 #endif
-		if (fh->vol) {
-			switch_change_sln_volume(write_frame.data, write_frame.datalen / 2, fh->vol);
-		}
-
-		fh->offset_pos += write_frame.samples / 2;
-		status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
-
-		if (status == SWITCH_STATUS_MORE_DATA) {
-			status = SWITCH_STATUS_SUCCESS;
-			continue;
-		} else if (status != SWITCH_STATUS_SUCCESS) {
-			done = 1;
-			break; 
-		}
+			if (fh->vol) {
+				switch_change_sln_volume(write_frame.data, write_frame.datalen / 2, fh->vol);
+			}
 
-		if (done) {
-			break; 
-		}
+			fh->offset_pos += write_frame.samples / 2;
+			status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
 
-		if (timer_name) {
-			if (switch_core_timer_next(&timer) != SWITCH_STATUS_SUCCESS) {
+			if (status == SWITCH_STATUS_MORE_DATA) {
+				status = SWITCH_STATUS_SUCCESS;
+				continue;
+			} else if (status != SWITCH_STATUS_SUCCESS) {
+				done = 1;
 				break; 
 			}
-		} else {				/* time off the channel (if you must) */
-			switch_frame_t *read_frame;
-			switch_status_t tstatus;
-			while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
-				switch_yield(10000);
-			}
 
-			tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
-
-			if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
+			if (done) {
 				break; 
 			}
 
-			if (args && (args->read_frame_callback)) {
-				int ok = 1;
-				switch_set_flag(fh, SWITCH_FILE_CALLBACK);
-				if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) {
-					ok = 0;
+			if (timer_name) {
+				if (switch_core_timer_next(&timer) != SWITCH_STATUS_SUCCESS) {
+					break; 
 				}
-				switch_clear_flag(fh, SWITCH_FILE_CALLBACK);
-				if (!ok) {
+			} else {				/* time off the channel (if you must) */
+				switch_frame_t *read_frame;
+				switch_status_t tstatus;
+				while (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_HOLD)) {
+					switch_yield(10000);
+				}
+
+				tstatus = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
+
+				if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
 					break; 
 				}
+
+				if (args && (args->read_frame_callback)) {
+					int ok = 1;
+					switch_set_flag(fh, SWITCH_FILE_CALLBACK);
+					if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) {
+						ok = 0;
+					}
+					switch_clear_flag(fh, SWITCH_FILE_CALLBACK);
+					if (!ok) {
+						break; 
+					}
+				}
 			}
 		}
-	}
 
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "done playing file\n");
-	//switch_core_file_seek(fh, &fh->last_pos, 0, SEEK_CUR);
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "done playing file\n");
+		
+		switch_channel_set_variable_printf(channel, "playback_ms", "%d", fh->samples_out / read_impl.samples_per_second);
+		switch_channel_set_variable_printf(channel, "playback_samples", "%d", fh->samples_out);
 
+		switch_core_file_close(fh);
 
-	switch_channel_set_variable_printf(channel, "playback_ms", "%d", fh->samples_out / read_impl.samples_per_second);
-	switch_channel_set_variable_printf(channel, "playback_samples", "%d", fh->samples_out);
+		if (fh->audio_buffer) {
+			switch_buffer_destroy(&fh->audio_buffer);
+		}
+		
+		if (fh->sp_audio_buffer) {
+			switch_buffer_destroy(&fh->sp_audio_buffer);
+		}
+	}
 
-	switch_core_file_close(fh);
-	switch_buffer_destroy(&fh->audio_buffer);
-	switch_buffer_destroy(&fh->sp_audio_buffer);
-	if (!asis) {
+	if (switch_core_codec_ready((&codec))) {
 		switch_core_codec_destroy(&codec);
 	}
-	if (timer_name) {
+
+	if (timer.samplecount) {
 		/* End the audio absorbing thread */
 		switch_core_thread_session_end(session);
 		switch_core_timer_destroy(&timer);
 	}
 
 
-  end:
+
 	switch_safe_free(abuf);
 
 	switch_core_session_reset(session, SWITCH_FALSE, SWITCH_TRUE);
@@ -1600,7 +1661,7 @@
 		memset(digit_buffer, 0, digit_buffer_length);
 		switch_channel_flush_dtmf(channel);
 		status = switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, var_name, 
-												 digit_buffer, digit_buffer_length, timeout, valid_terminators);
+								 digit_buffer, digit_buffer_length, timeout, valid_terminators);
 		if (status == SWITCH_STATUS_TIMEOUT && strlen(digit_buffer) >= min_digits) {
 			status = SWITCH_STATUS_SUCCESS;
 		}



More information about the Freeswitch-svn mailing list