From d9ce90d7b9cd35705ab03a42953b6bf866a9caf8 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Fri, 16 Sep 2011 11:39:41 -0500
Subject: [PATCH] FS-3570 generate side

---
 src/switch_channel.c   |  2 +-
 src/switch_core.c      | 18 ++++++++++++++++++
 src/switch_ivr_async.c | 33 ++++++++++++++++++++++++++-------
 3 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/src/switch_channel.c b/src/switch_channel.c
index 2055e8fc07..a8669f1602 100644
--- a/src/switch_channel.c
+++ b/src/switch_channel.c
@@ -446,7 +446,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf_string(switch_channel_
 		dur = switch_core_default_dtmf_duration(0) / 8;
 		if ((p = strchr(argv[i], '@'))) {
 			*p++ = '\0';
-			if ((dur = atoi(p)) > 50) {
+			if ((dur = atoi(p)) > switch_core_min_dtmf_duration(0) / 8) {
 				dtmf.duration = dur * 8;
 			}
 		}
diff --git a/src/switch_core.c b/src/switch_core.c
index 045ff3978c..85a710c085 100644
--- a/src/switch_core.c
+++ b/src/switch_core.c
@@ -1263,6 +1263,9 @@ SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration)
 			duration = SWITCH_MIN_DTMF_DURATION;
 		}
 		runtime.max_dtmf_duration = duration;
+		if (duration < runtime.min_dtmf_duration) {
+			runtime.min_dtmf_duration = duration;
+		}
 	}
 	return runtime.max_dtmf_duration;
 }
@@ -1277,6 +1280,15 @@ SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration)
 			duration = SWITCH_MAX_DTMF_DURATION;
 		}
 		runtime.default_dtmf_duration = duration;
+
+		if (duration < runtime.min_dtmf_duration) {
+			runtime.min_dtmf_duration = duration;
+		}
+
+		if (duration > runtime.max_dtmf_duration) {
+			runtime.max_dtmf_duration = duration;
+		}
+
 	}
 	return runtime.default_dtmf_duration;
 }
@@ -1290,6 +1302,12 @@ SWITCH_DECLARE(uint32_t) switch_core_min_dtmf_duration(uint32_t duration)
 		if (duration > SWITCH_MAX_DTMF_DURATION) {
 			duration = SWITCH_MAX_DTMF_DURATION;
 		}
+
+		runtime.min_dtmf_duration = duration;
+
+		if (duration > runtime.max_dtmf_duration) {
+			runtime.max_dtmf_duration = duration;
+		}
 	}
 	return runtime.min_dtmf_duration;
 }
diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c
index b5d0591ec5..6fe6048173 100644
--- a/src/switch_ivr_async.c
+++ b/src/switch_ivr_async.c
@@ -2229,6 +2229,7 @@ typedef struct {
 	switch_mutex_t *mutex;
 	int read;
 	int ready;
+	int skip;
 } switch_inband_dtmf_generate_t;
 
 static int teletone_dtmf_generate_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map)
@@ -2257,13 +2258,17 @@ static switch_status_t generate_on_dtmf(switch_core_session_t *session, const sw
 
 		if (pvt) {
 			switch_mutex_lock(pvt->mutex);
+			
 			if (pvt->ready) {
 				switch_dtmf_t *dt = NULL;
 				switch_zmalloc(dt, sizeof(*dt));
 				*dt = *dtmf;
+				if (!switch_buffer_inuse(pvt->audio_buffer)) {
+					pvt->skip = 10;
+				}
 				if (switch_queue_trypush(pvt->digit_queue, dt) == SWITCH_STATUS_SUCCESS) {
 					switch_event_t *event;
-					
+
 					if (switch_event_create(&event, SWITCH_EVENT_DTMF) == SWITCH_STATUS_SUCCESS) {
 						switch_channel_event_set_data(channel, event);
 						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Digit", "%c", dtmf->digit);
@@ -2310,7 +2315,11 @@ static switch_bool_t inband_dtmf_generate_callback(switch_media_bug_t *bug, void
 			pvt->ts.rate = read_impl.actual_samples_per_second;
 			pvt->ts.channels = 1;
 			switch_mutex_init(&pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(pvt->session));
-			switch_core_event_hook_add_recv_dtmf(pvt->session, generate_on_dtmf);
+			if (pvt->read) {
+				switch_core_event_hook_add_recv_dtmf(pvt->session, generate_on_dtmf);
+			} else {
+				switch_core_event_hook_add_send_dtmf(pvt->session, generate_on_dtmf);
+			}
 			switch_mutex_lock(pvt->mutex);
 			pvt->ready = 1;
 			switch_mutex_unlock(pvt->mutex);
@@ -2331,6 +2340,12 @@ static switch_bool_t inband_dtmf_generate_callback(switch_media_bug_t *bug, void
 		{
 			switch_size_t bytes;
 			void *pop;
+			
+			if (pvt->skip) {
+				pvt->skip--;
+				return SWITCH_TRUE;
+			}
+			
 
 			switch_mutex_lock(pvt->mutex);
 
@@ -2348,17 +2363,21 @@ static switch_bool_t inband_dtmf_generate_callback(switch_media_bug_t *bug, void
 			if (!switch_buffer_inuse(pvt->audio_buffer)) {
 				if (switch_queue_trypop(pvt->digit_queue, &pop) == SWITCH_STATUS_SUCCESS) {
 					switch_dtmf_t *dtmf = (switch_dtmf_t *) pop;
+					
+
 					if (dtmf->source != SWITCH_DTMF_INBAND_AUDIO) {
 						char buf[2] = "";
 						int duration = dtmf->duration;
 
 						buf[0] = dtmf->digit;
-						if (duration > 8000) {
-							duration = 4000;
+						if (duration > switch_core_max_dtmf_duration(0)) {
+							duration = switch_core_default_dtmf_duration(0);
 							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)),
-										  SWITCH_LOG_WARNING, "%s Truncating ridiculous DTMF duration %d ms to 1/2 second.\n",
-										  switch_channel_get_name(switch_core_session_get_channel(pvt->session)), dtmf->duration / 8);
+										  SWITCH_LOG_WARNING, "%s Truncating DTMF duration %d ms to %d ms\n",
+											  switch_channel_get_name(switch_core_session_get_channel(pvt->session)), dtmf->duration / 8, duration);
 						}
+						
+
 						pvt->ts.duration = duration;
 						teletone_run(&pvt->ts, buf);
 					}
@@ -2429,7 +2448,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_inband_dtmf_generate_session(switch_c
 
 	if ((status = switch_core_media_bug_add(session, "inband_dtmf_generate", NULL,
 											inband_dtmf_generate_callback, pvt, 0,
-											SMBF_NO_PAUSE | pvt->read ? SMBF_READ_REPLACE : SMBF_WRITE_REPLACE , &bug)) != SWITCH_STATUS_SUCCESS) {
+											SMBF_NO_PAUSE | (pvt->read ? SMBF_READ_REPLACE : SMBF_WRITE_REPLACE) , &bug)) != SWITCH_STATUS_SUCCESS) {
 		return status;
 	}