[Freeswitch-trunk] [commit] r6952 - in freeswitch/trunk/src: . include include/private mod/applications/mod_conference mod/applications/mod_dptools mod/applications/mod_fifo mod/applications/mod_rss mod/applications/mod_voicemail mod/endpoints/mod_alsa mod/endpoints/mod_dingaling mod/endpoints/mod_iax mod/endpoints/mod_portaudio mod/endpoints/mod_sofia mod/endpoints/mod_wanpipe mod/languages/mod_spidermonkey mod/languages/mod_spidermonkey_teletone

Freeswitch SVN anthm at freeswitch.org
Fri Dec 21 19:32:21 EST 2007


Author: anthm
Date: Fri Dec 21 19:32:20 2007
New Revision: 6952

Modified:
   freeswitch/trunk/src/include/private/switch_core_pvt.h
   freeswitch/trunk/src/include/switch_channel.h
   freeswitch/trunk/src/include/switch_core.h
   freeswitch/trunk/src/include/switch_core_event_hook.h
   freeswitch/trunk/src/include/switch_module_interfaces.h
   freeswitch/trunk/src/include/switch_rtp.h
   freeswitch/trunk/src/include/switch_types.h
   freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c
   freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
   freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c
   freeswitch/trunk/src/mod/applications/mod_rss/mod_rss.c
   freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c
   freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c
   freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
   freeswitch/trunk/src/mod/endpoints/mod_iax/mod_iax.c
   freeswitch/trunk/src/mod/endpoints/mod_portaudio/mod_portaudio.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
   freeswitch/trunk/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c
   freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
   freeswitch/trunk/src/mod/languages/mod_spidermonkey_teletone/mod_spidermonkey_teletone.c
   freeswitch/trunk/src/switch_channel.c
   freeswitch/trunk/src/switch_core.c
   freeswitch/trunk/src/switch_core_io.c
   freeswitch/trunk/src/switch_core_session.c
   freeswitch/trunk/src/switch_cpp.cpp
   freeswitch/trunk/src/switch_ivr.c
   freeswitch/trunk/src/switch_ivr_async.c
   freeswitch/trunk/src/switch_ivr_bridge.c
   freeswitch/trunk/src/switch_ivr_play_say.c
   freeswitch/trunk/src/switch_rtp.c

Log:
dtmf overhaul testers wanted

Modified: freeswitch/trunk/src/include/private/switch_core_pvt.h
==============================================================================
--- freeswitch/trunk/src/include/private/switch_core_pvt.h	(original)
+++ freeswitch/trunk/src/include/private/switch_core_pvt.h	Fri Dec 21 19:32:20 2007
@@ -168,6 +168,7 @@
 	uint32_t flags;
 	switch_time_t timestamp;
 	switch_mutex_t *throttle_mutex;
+	switch_mutex_t *global_mutex;
 	uint32_t sps_total;
 	int32_t sps;
 	int32_t sps_last;

Modified: freeswitch/trunk/src/include/switch_channel.h
==============================================================================
--- freeswitch/trunk/src/include/switch_channel.h	(original)
+++ freeswitch/trunk/src/include/switch_channel.h	Fri Dec 21 19:32:20 2007
@@ -422,19 +422,20 @@
 /*!
   \brief Queue DTMF on a given channel
   \param channel channel to queue DTMF to
-  \param dtmf string of digits to queue
+  \param dtmf digit
   \return SWITCH_STATUS_SUCCESS if successful
 */
-SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *channel, const char *dtmf);
+SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *channel, const switch_dtmf_t *dtmf);
 
 /*!
   \brief Retrieve DTMF digits from a given channel
   \param channel channel to retrieve digits from
-  \param dtmf buffer to write dtmf to
-  \param len max size in bytes of the buffer
+  \param dtmf digit
   \return number of bytes read into the buffer
 */
-SWITCH_DECLARE(switch_size_t) switch_channel_dequeue_dtmf(switch_channel_t *channel, char *dtmf, switch_size_t len);
+SWITCH_DECLARE(switch_status_t) switch_channel_dequeue_dtmf(switch_channel_t *channel, switch_dtmf_t *dtmf);
+SWITCH_DECLARE(void) switch_channel_flush_dtmf(switch_channel_t *channel);
+SWITCH_DECLARE(switch_size_t) switch_channel_dequeue_dtmf_string(switch_channel_t *channel, char *dtmf_str, switch_size_t len);
 
 /*!
   \brief Render the name of the provided state enum

Modified: freeswitch/trunk/src/include/switch_core.h
==============================================================================
--- freeswitch/trunk/src/include/switch_core.h	(original)
+++ freeswitch/trunk/src/include/switch_core.h	Fri Dec 21 19:32:20 2007
@@ -829,7 +829,7 @@
   \param dtmf string to send to the session
   \return SWITCH_STATUS_SUCCESS if the dtmf was written
 */
-SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_session_t *session, const char *dtmf);
+SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf);
 
 /*! 
   \brief RECV DTMF on a session
@@ -837,7 +837,7 @@
   \param dtmf string to recv from the session
   \return SWITCH_STATUS_SUCCESS if the dtmf is ok to queue
 */
-SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_session_t *session, const char *dtmf);
+SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf);
 
 ///\}
 

Modified: freeswitch/trunk/src/include/switch_core_event_hook.h
==============================================================================
--- freeswitch/trunk/src/include/switch_core_event_hook.h	(original)
+++ freeswitch/trunk/src/include/switch_core_event_hook.h	Fri Dec 21 19:32:20 2007
@@ -59,8 +59,8 @@
 typedef switch_status_t (*switch_kill_channel_hook_t) (switch_core_session_t *, int);
 typedef switch_status_t (*switch_waitfor_read_hook_t) (switch_core_session_t *, int, int);
 typedef switch_status_t (*switch_waitfor_write_hook_t) (switch_core_session_t *, int, int);
-typedef switch_status_t (*switch_send_dtmf_hook_t) (switch_core_session_t *, const char *);
-typedef switch_status_t (*switch_recv_dtmf_hook_t) (switch_core_session_t *, const char *);
+typedef switch_status_t (*switch_send_dtmf_hook_t) (switch_core_session_t *, const switch_dtmf_t *);
+typedef switch_status_t (*switch_recv_dtmf_hook_t) (switch_core_session_t *, const switch_dtmf_t *);
 typedef switch_status_t (*switch_state_change_hook_t) (switch_core_session_t *);
 
 

Modified: freeswitch/trunk/src/include/switch_module_interfaces.h
==============================================================================
--- freeswitch/trunk/src/include/switch_module_interfaces.h	(original)
+++ freeswitch/trunk/src/include/switch_module_interfaces.h	Fri Dec 21 19:32:20 2007
@@ -105,7 +105,7 @@
 typedef switch_status_t (*switch_io_kill_channel_t) (switch_core_session_t *, int);
 typedef switch_status_t (*switch_io_waitfor_read_t) (switch_core_session_t *, int, int);
 typedef switch_status_t (*switch_io_waitfor_write_t) (switch_core_session_t *, int, int);
-typedef switch_status_t (*switch_io_send_dtmf_t) (switch_core_session_t *, char *);
+typedef switch_status_t (*switch_io_send_dtmf_t) (switch_core_session_t *, const switch_dtmf_t *);
 typedef switch_status_t (*switch_io_receive_message_t) (switch_core_session_t *, switch_core_session_message_t *);
 typedef switch_status_t (*switch_io_receive_event_t) (switch_core_session_t *, switch_event_t *);
 typedef switch_status_t (*switch_io_state_change_t) (switch_core_session_t *);

Modified: freeswitch/trunk/src/include/switch_rtp.h
==============================================================================
--- freeswitch/trunk/src/include/switch_rtp.h	(original)
+++ freeswitch/trunk/src/include/switch_rtp.h	Fri Dec 21 19:32:20 2007
@@ -261,7 +261,8 @@
   \param digits the digit string to queue
   \param duration the duration of the dtmf
 */
-SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_session, char *digits, uint32_t duration);
+SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_session, const switch_dtmf_t *dtmf);
+SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833_in(switch_rtp_t *rtp_session, const switch_dtmf_t *dtmf);
 
 /*!
   \brief Test for presence of DTMF on a given RTP session
@@ -271,21 +272,12 @@
 SWITCH_DECLARE(switch_size_t) switch_rtp_has_dtmf(switch_rtp_t *rtp_session);
 
 /*!
-  \brief Queue DTMF on a given RTP session
-  \param rtp_session RTP session to queue DTMF to
-  \param dtmf string of digits to queue
-  \return SWITCH_STATUS_SUCCESS if successful
-*/
-SWITCH_DECLARE(switch_status_t) switch_rtp_queue_dtmf(switch_rtp_t *rtp_session, char *dtmf);
-
-/*!
   \brief Retrieve DTMF digits from a given RTP session
   \param rtp_session RTP session to retrieve digits from
-  \param dtmf buffer to write dtmf to
-  \param len max size in bytes of the buffer
+  \param dtmf the dtmf
   \return number of bytes read into the buffer
 */
-SWITCH_DECLARE(switch_size_t) switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session, char *dtmf, switch_size_t len);
+SWITCH_DECLARE(switch_size_t) switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session, switch_dtmf_t *dtmf);
 
 /*! 
   \brief Read data from a given RTP session without copying

Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h	(original)
+++ freeswitch/trunk/src/include/switch_types.h	Fri Dec 21 19:32:20 2007
@@ -92,7 +92,7 @@
 #define SWITCH_SEQ_CLEARLINEEND SWITCH_SEQ_ESC SWITCH_SEQ_CLEARLINEEND_CHAR
 #define SWITCH_SEQ_CLEARSCR SWITCH_SEQ_ESC SWITCH_SEQ_CLEARSCR_CHAR SWITCH_SEQ_HOME
 
-
+#define SWITCH_DEFAULT_DTMF_DURATION 250
 #define SWITCH_DEFAULT_DIR_PERMS SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE | SWITCH_FPROT_UEXECUTE | SWITCH_FPROT_GREAD | SWITCH_FPROT_GEXECUTE
 
 #ifdef WIN32
@@ -136,6 +136,11 @@
 #define SWITCH_BITS_PER_BYTE 8
 typedef uint8_t switch_byte_t;
 
+typedef struct {
+	char digit;
+	uint32_t duration;
+} switch_dtmf_t;
+
 typedef enum {
 	SOF_NONE = 0,
 	SOF_NOBLOCK = (1 << 0),

Modified: freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c	Fri Dec 21 19:32:20 2007
@@ -1648,7 +1648,7 @@
 
 		/* if we have caller digits, feed them to the parser to find an action */
 		if (switch_channel_has_dtmf(channel)) {
-			switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
+			switch_channel_dequeue_dtmf_string(channel, dtmf, sizeof(dtmf));
 
 			if (member->conference->dtmf_parser != NULL) {
 
@@ -2637,6 +2637,8 @@
 {
 	switch_event_t *event;
 	char *dtmf = (char *) data;
+	char *p = dtmf;
+	switch_dtmf_t _dtmf = { 0, SWITCH_DEFAULT_DTMF_DURATION };
 
 	if (member == NULL) {
 		stream->write_function(stream, "Invalid member!\n");
@@ -2651,9 +2653,15 @@
 
 	switch_mutex_lock(member->flag_mutex);
 	switch_core_session_kill_channel(member->session, SWITCH_SIG_BREAK);
-	switch_core_session_send_dtmf(member->session, dtmf);
-	switch_mutex_unlock(member->flag_mutex);
 
+	while(p && *p) {
+		_dtmf.digit = *p;
+		switch_core_session_send_dtmf(member->session, &_dtmf);
+		p++;
+	}
+
+	switch_mutex_unlock(member->flag_mutex);
+	
 
 	if (stream != NULL) {
 		stream->write_function(stream, "OK sent %s to %u\n", (char *) data, member->id);

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	Fri Dec 21 19:32:20 2007
@@ -193,10 +193,17 @@
 SWITCH_STANDARD_APP(queue_dtmf_function)
 {
 	switch_channel_t *channel;
+	char *p;
+	switch_dtmf_t dtmf = {0, SWITCH_DEFAULT_DTMF_DURATION};
+
 	if (!switch_strlen_zero(data)) {
 		channel = switch_core_session_get_channel(session);
 		assert(channel != NULL);
-		switch_channel_queue_dtmf(channel, data);
+		for (p = (char *)data; p && *p; p++) {
+			dtmf.digit = *p;
+			switch_channel_queue_dtmf(channel, &dtmf);
+			p++;
+		}
 	}
 }
 
@@ -1048,7 +1055,7 @@
 	switch (itype) {
 	case SWITCH_INPUT_TYPE_DTMF:
 		{
-			char *dtmf = (char *) input;
+			switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
 			const char *terminators;
 			switch_channel_t *channel = switch_core_session_get_channel(session);
 			const char *p;
@@ -1061,14 +1068,11 @@
 			if (!strcasecmp(terminators, "none")) {
 				terminators = NULL;
 			}
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Digits %s\n", dtmf);
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Digit %c\n", dtmf->digit);
 			
 			for (p = terminators; p && *p; p++) {
-				char *d;
-				for (d = dtmf; d && *d; d++) {
-					if (*p == *d) {
-						return SWITCH_STATUS_BREAK;
-					}
+				if (*p == dtmf->digit) {
+					return SWITCH_STATUS_BREAK;
 				}
 			}
 		}

Modified: freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c	Fri Dec 21 19:32:20 2007
@@ -48,8 +48,9 @@
 	switch (itype) {
 	case SWITCH_INPUT_TYPE_DTMF:
         {
-            char *dtmf = (char *) input;
-            if (*dtmf == '*') {
+            switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
+
+            if (dtmf->digit == '*') {
                 channel = switch_core_session_get_channel(session);
                 if (switch_channel_test_flag(channel, CF_ORIGINATOR)) {
                     channel = switch_core_session_get_channel(bleg);

Modified: freeswitch/trunk/src/mod/applications/mod_rss/mod_rss.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_rss/mod_rss.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_rss/mod_rss.c	Fri Dec 21 19:32:20 2007
@@ -91,11 +91,11 @@
 {
 	switch (itype) {
 	case SWITCH_INPUT_TYPE_DTMF:{
-			char *dtmf = (char *) input;
+		switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
 			struct dtmf_buffer *dtb;
 			dtb = (struct dtmf_buffer *) buf;
 
-			switch (*dtmf) {
+			switch (dtmf->digit) {
 			case '#':
 				switch_set_flag(dtb, SFLAG_MAIN);
 				return SWITCH_STATUS_BREAK;

Modified: freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c	Fri Dec 21 19:32:20 2007
@@ -615,9 +615,11 @@
 	switch (itype) {
 	case SWITCH_INPUT_TYPE_DTMF:
         {
-            char *dtmf = (char *) input;
+            switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
             if (buf && buflen) {
-                switch_copy_string(buf, dtmf, buflen);
+                char *bp = (char *) buf;
+                bp[0] = dtmf->digit;
+                bp[1] = '\0';
             }
             return SWITCH_STATUS_BREAK;
         }
@@ -643,13 +645,13 @@
 	switch (itype) {
 	case SWITCH_INPUT_TYPE_DTMF:
         {
-            char *dtmf = (char *) input;
+            switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
             cc_t *cc = (cc_t *) buf;
             switch_file_handle_t *fh = cc->fh;
             uint32_t pos = 0;
 
-            if (!cc->noexit && (*dtmf == *cc->profile->delete_file_key || *dtmf == *cc->profile->save_file_key || *dtmf == *cc->profile->terminator_key)) {
-                *cc->buf = *dtmf;
+            if (!cc->noexit && (dtmf->digit == *cc->profile->delete_file_key || dtmf->digit == *cc->profile->save_file_key || dtmf->digit == *cc->profile->terminator_key)) {
+                *cc->buf = dtmf->digit;
                 return SWITCH_STATUS_BREAK;
             }
 
@@ -657,7 +659,7 @@
                 return SWITCH_STATUS_SUCCESS;
             }
 
-            if (*dtmf == *cc->profile->pause_key) {
+            if (dtmf->digit == *cc->profile->pause_key) {
                 if (switch_test_flag(fh, SWITCH_FILE_PAUSE)) {
                     switch_clear_flag(fh, SWITCH_FILE_PAUSE);
                 } else {
@@ -666,20 +668,20 @@
                 return SWITCH_STATUS_SUCCESS;
             }
 
-            if (*dtmf == *cc->profile->restart_key) {
+            if (dtmf->digit == *cc->profile->restart_key) {
                 unsigned int seekpos = 0;
                 fh->speed = 0;
                 switch_core_file_seek(fh, &seekpos, 0, SEEK_SET);
                 return SWITCH_STATUS_SUCCESS;
             }
 
-            if (*dtmf == *cc->profile->ff_key) {
+            if (dtmf->digit == *cc->profile->ff_key) {
                 int samps = 24000;
                 switch_core_file_seek(fh, &pos, samps, SEEK_CUR);
                 return SWITCH_STATUS_SUCCESS;
             }
 
-            if (*dtmf == *cc->profile->rew_key) {
+            if (dtmf->digit == *cc->profile->rew_key) {
                 int samps = 24000;
                 switch_core_file_seek(fh, &pos, fh->pos - samps, SEEK_SET);
                 return SWITCH_STATUS_SUCCESS;

Modified: freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c	Fri Dec 21 19:32:20 2007
@@ -522,14 +522,14 @@
 
 }
 
-static switch_status_t channel_send_dtmf(switch_core_session_t *session, char *dtmf)
+static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
 {
 	private_t *tech_pvt = NULL;
 
 	tech_pvt = switch_core_session_get_private(session);
 	assert(tech_pvt != NULL);
 
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF ON CALL %s [%s]\n", tech_pvt->call_id, dtmf);
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF ON CALL %s [%c]\n", tech_pvt->call_id, dtmf->digit);
 
 	return SWITCH_STATUS_SUCCESS;
 }
@@ -1205,15 +1205,21 @@
 
 static switch_status_t dtmf_call(char **argv, int argc, switch_stream_handle_t *stream)
 {
-	char *dtmf = argv[0];
-
-	if (switch_strlen_zero(dtmf)) {
+	char *dtmf_str = argv[0];
+	switch_dtmf_t dtmf = {0, SWITCH_DEFAULT_DTMF_DURATION};
+	
+	if (switch_strlen_zero(dtmf_str)) {
 		stream->write_function(stream, "No DTMF Supplied!\n");
 	} else {
 		switch_mutex_lock(globals.pvt_lock);
 		if (globals.call_list) {
 			switch_channel_t *channel = switch_core_session_get_channel(globals.call_list->session);
-			switch_channel_queue_dtmf(channel, dtmf);
+			char *p = dtmf_str;
+			while(p && *p) {
+				dtmf.digit = *p;
+				switch_channel_queue_dtmf(channel, &dtmf);
+				p++;
+			}
 		}
 		switch_mutex_unlock(globals.pvt_lock);
 	}

Modified: freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c	Fri Dec 21 19:32:20 2007
@@ -1344,7 +1344,7 @@
 
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF [%s]\n", dtmf);
 
-	return switch_rtp_queue_rfc2833(tech_pvt->rtp_session, dtmf, 100 * (tech_pvt->read_codec.implementation->samples_per_second / 1000));
+	return switch_rtp_queue_rfc2833(tech_pvt->rtp_session, dtmf);
 
 }
 
@@ -1416,9 +1416,9 @@
 			}
 #endif
 			if (switch_rtp_has_dtmf(tech_pvt->rtp_session)) {
-				char dtmf[128];
-				switch_rtp_dequeue_dtmf(tech_pvt->rtp_session, dtmf, sizeof(dtmf));
-				switch_channel_queue_dtmf(channel, dtmf);
+				switch_dtmf_t dtmf = { 0 };
+				switch_rtp_dequeue_dtmf(tech_pvt->rtp_session, &dtmf);
+				switch_channel_queue_dtmf(channel, &dtmf);
 			}
 
 
@@ -2722,7 +2722,13 @@
 	case LDL_SIGNAL_MSG:
 		if (msg) {
 			if (*msg == '+') {
-				switch_channel_queue_dtmf(channel, msg + 1);
+				char *p = msg + 1;
+				switch_dtmf_t dtmf = { 0, SWITCH_DEFAULT_DTMF_DURATION };
+				while (p && *p) {
+					dtmf.digit = *p;
+					switch_channel_queue_dtmf(channel, &dtmf);
+					p++;
+				}
 				switch_set_flag_locked(tech_pvt, TFLAG_DTMF);
 				if (switch_rtp_ready(tech_pvt->rtp_session)) {
 					switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_BREAK);

Modified: freeswitch/trunk/src/mod/endpoints/mod_iax/mod_iax.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_iax/mod_iax.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_iax/mod_iax.c	Fri Dec 21 19:32:20 2007
@@ -620,17 +620,14 @@
 
 }
 
-static switch_status_t channel_send_dtmf(switch_core_session_t *session, char *dtmf)
+static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
 {
 	private_t *tech_pvt = NULL;
-	char *digit;
-
+	
 	tech_pvt = switch_core_session_get_private(session);
 	switch_assert(tech_pvt != NULL);
 	if (tech_pvt->iax_session) {
-		for (digit = dtmf; *digit; digit++) {
-			iax_send_dtmf(tech_pvt->iax_session, *digit);
-		}
+		iax_send_dtmf(tech_pvt->iax_session, dtmf->digit);
 	}
 
 	return SWITCH_STATUS_SUCCESS;
@@ -1206,11 +1203,12 @@
 				break;
 			case IAX_EVENT_DTMF:
 				if (channel) {
-					char str[2] = { (char) iaxevent->subclass };
+					switch_dtmf_t dtmf = { (char) iaxevent->subclass , SWITCH_DEFAULT_DTMF_DURATION };
 					if (globals.debug) {
-						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s DTMF %s\n", str, switch_channel_get_name(channel));
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%c DTMF %s\n", dtmf.digit, switch_channel_get_name(channel));
 					}
-					switch_channel_queue_dtmf(channel, str);
+					
+					switch_channel_queue_dtmf(channel, &dtmf);
 				}
 
 				break;

Modified: freeswitch/trunk/src/mod/endpoints/mod_portaudio/mod_portaudio.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_portaudio/mod_portaudio.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_portaudio/mod_portaudio.c	Fri Dec 21 19:32:20 2007
@@ -524,14 +524,14 @@
 
 }
 
-static switch_status_t channel_send_dtmf(switch_core_session_t *session, char *dtmf)
+static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
 {
 	private_t *tech_pvt = NULL;
 
 	tech_pvt = switch_core_session_get_private(session);
 	switch_assert(tech_pvt != NULL);
 
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF ON CALL %s [%s]\n", tech_pvt->call_id, dtmf);
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF ON CALL %s [%c]\n", tech_pvt->call_id, dtmf->digit);
 
 	return SWITCH_STATUS_SUCCESS;
 }
@@ -1314,18 +1314,23 @@
 
 
 
-
 static switch_status_t dtmf_call(char **argv, int argc, switch_stream_handle_t *stream)
 {
-	char *dtmf = argv[0];
-
-	if (switch_strlen_zero(dtmf)) {
+	char *dtmf_str = argv[0];
+	switch_dtmf_t dtmf = {0, SWITCH_DEFAULT_DTMF_DURATION};
+	
+	if (switch_strlen_zero(dtmf_str)) {
 		stream->write_function(stream, "No DTMF Supplied!\n");
 	} else {
 		switch_mutex_lock(globals.pvt_lock);
 		if (globals.call_list) {
 			switch_channel_t *channel = switch_core_session_get_channel(globals.call_list->session);
-			switch_channel_queue_dtmf(channel, dtmf);
+			char *p = dtmf_str;
+			while(p && *p) {
+				dtmf.digit = *p;
+				switch_channel_queue_dtmf(channel, &dtmf);
+				p++;
+			}
 		}
 		switch_mutex_unlock(globals.pvt_lock);
 	}

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	Fri Dec 21 19:32:20 2007
@@ -540,9 +540,9 @@
 			payload = tech_pvt->read_frame.payload;
 
 			if (switch_rtp_has_dtmf(tech_pvt->rtp_session)) {
-				char dtmf[128];
-				switch_rtp_dequeue_dtmf(tech_pvt->rtp_session, dtmf, sizeof(dtmf));
-				switch_channel_queue_dtmf(channel, dtmf);
+				switch_dtmf_t dtmf = {0};
+				switch_rtp_dequeue_dtmf(tech_pvt->rtp_session, &dtmf);
+				switch_channel_queue_dtmf(channel, &dtmf);
 			}
 
 
@@ -696,15 +696,31 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
-static switch_status_t sofia_send_dtmf(switch_core_session_t *session, char *digits)
+static switch_status_t sofia_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
 {
 	private_object_t *tech_pvt;
+	char message[128] = "";
 
 	tech_pvt = (private_object_t *) switch_core_session_get_private(session);
 	switch_assert(tech_pvt != NULL);
 
-	return switch_rtp_queue_rfc2833(tech_pvt->rtp_session,
-									digits, tech_pvt->profile->dtmf_duration * (tech_pvt->read_codec.implementation->samples_per_second / 1000));
+	switch (tech_pvt->dtmf_type) {
+	case DTMF_2833:
+		return switch_rtp_queue_rfc2833(tech_pvt->rtp_session, dtmf);
+
+	case DTMF_INFO:
+		snprintf(message, sizeof(message), "Signal=%c\r\nDuration=%d\r\n", dtmf->digit, dtmf->duration);
+		nua_info(tech_pvt->nh,
+				 //NUTAG_WITH_THIS(tech_pvt->profile->nua),
+				 SIPTAG_CONTENT_TYPE_STR("application/dtmf-relay"),
+				 SIPTAG_PAYLOAD_STR(message),
+				 TAG_END());
+		break;
+	default:
+		break;
+	}
+
+	return SWITCH_STATUS_SUCCESS;
 }
 
 static switch_status_t sofia_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	Fri Dec 21 19:32:20 2007
@@ -83,6 +83,13 @@
 #include <sofia-sip/nea.h>
 #include <sofia-sip/msg_addr.h>
 
+
+typedef enum {
+	DTMF_2833,
+	DTMF_INFO,
+	DTMF_NONE
+} sofia_dtmf_t;
+
 struct sofia_private {
 	char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1];
 	sofia_gateway_t *gateway;
@@ -232,6 +239,8 @@
 	char *tls_cert_dir;
 	char *reg_domain;
 	char *user_agent;
+	char *record_template;
+	sofia_dtmf_t dtmf_type;
 	int sip_port;
 	int tls_sip_port;
 	char *codec_string;
@@ -357,6 +366,7 @@
 	switch_payload_t video_agreed_pt;
 	char *video_fmtp_out;
 	uint32_t video_count;
+	sofia_dtmf_t dtmf_type;
 };
 
 struct callback_t {
@@ -547,3 +557,4 @@
 const char *sofia_glue_transport2str(const sofia_transport_t tp);
 
 int sofia_glue_transport_has_tls(const sofia_transport_t tp);
+const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name);

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	Fri Dec 21 19:32:20 2007
@@ -884,6 +884,16 @@
 
 					} else if (!strcasecmp(var, "user-agent-string")) {
 						profile->user_agent = switch_core_strdup(profile->pool, val);;
+					} else if (!strcasecmp(var, "dtmf-type")) {
+						if (!strcasecmp(val, "rfc2833")) {
+							profile->dtmf_type = DTMF_2833;
+						} else if (!strcasecmp(val, "info")) {
+							profile->dtmf_type = DTMF_INFO;
+						} else {
+							profile->dtmf_type = DTMF_NONE;
+						}
+					} else if (!strcasecmp(var, "record-template")) {
+						profile->record_template = switch_core_strdup(profile->pool, val);;
 					} else if (!strcasecmp(var, "inbound-no-media") && switch_true(val)) {
 						switch_set_flag(profile, TFLAG_INB_NOMEDIA);
 					} else if (!strcasecmp(var, "inbound-late-negotiation") && switch_true(val)) {
@@ -1916,57 +1926,108 @@
 {
 	struct private_object *tech_pvt = NULL;
 	switch_channel_t *channel = NULL;
-	char dtmf_digit[2] = { 0, 0 };
-
 	/* placeholder for string searching */
 	char *signal_ptr;
+	const char *rec_header;
 
-	/* Try and find signal information in the payload */
-	signal_ptr = strstr(sip->sip_payload->pl_data, "Signal=");
+	if (session) {
+		/* Get the channel */
+		channel = switch_core_session_get_channel(session);
 
-	/* unknown info type */
-	if (!signal_ptr) {
-		sip_from_t const *from = sip->sip_from;
-
-		/* print in the logs if something comes through we don't understand */
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unknown INFO Recieved: %s%s" URL_PRINT_FORMAT "[%s]\n",
-			from->a_display ? from->a_display : "",
-			from->a_display ? " " : "",
-			URL_PRINT_ARGS(from->a_url),
-			sip->sip_payload->pl_data);
-		/* Send 415 Unsupported Media response */
-		nua_respond(nh, SIP_415_UNSUPPORTED_MEDIA, NUTAG_WITH_THIS(nua), TAG_END());
-		return;
-	}
+		/* Barf if we didn't get it */
+		switch_assert(channel != NULL);
+		
+		/* make sure we have our privates */
+		tech_pvt = switch_core_session_get_private(session);
+	
+		/* Barf if we didn't get it */
+		switch_assert(tech_pvt != NULL);
 
-	/* Get the channel */
-	channel = switch_core_session_get_channel(session);
 
-	/* Barf if we didn't get it */
-	switch_assert(channel != NULL);
+		if (sip && sip->sip_payload && sip->sip_payload->pl_data) {
+			switch_dtmf_t dtmf = { 0, SWITCH_DEFAULT_DTMF_DURATION };
 
-	/* make sure we have our privates */
-	tech_pvt = switch_core_session_get_private(session);
+			/* Try and find signal information in the payload */
+			if ((signal_ptr = strstr(sip->sip_payload->pl_data, "Signal="))) {
+				/* move signal_ptr where we need it (right past Signal=) */
+				signal_ptr = signal_ptr + 7;
+			} else {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Bad signal\n");
+				return;
+			}
+
+			/* unknown info type */
+			if (!signal_ptr) {
+				sip_from_t const *from = sip->sip_from;
+
+				/* print in the logs if something comes through we don't understand */
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unknown INFO Recieved: %s%s" URL_PRINT_FORMAT "[%s]\n",
+								  from->a_display ? from->a_display : "",
+								  from->a_display ? " " : "",
+								  URL_PRINT_ARGS(from->a_url),
+								  sip->sip_payload->pl_data);
+				/* Send 415 Unsupported Media response */
+				nua_respond(nh, SIP_415_UNSUPPORTED_MEDIA, NUTAG_WITH_THIS(nua), TAG_END());
+				return;
+			}
 
-	/* Barf if we didn't get it */
-	switch_assert(tech_pvt != NULL);
+			
+			dtmf.digit = *signal_ptr;
+			if ((signal_ptr = strstr(sip->sip_payload->pl_data, "Duration="))) {
+				int tmp;
+				signal_ptr += 8;
+				if ((tmp = atoi(signal_ptr)) < 0) {
+					tmp = SWITCH_DEFAULT_DTMF_DURATION;
+				} 
+				dtmf.duration = tmp;
+			}
 
-	/* move signal_ptr where we need it (right past Signal=) */
-	signal_ptr = signal_ptr + 7;
+			/* queue it up */
+			switch_channel_queue_dtmf(channel, &dtmf);
 
-	/* put the digit somewhere we can muck with */
-	strncpy(dtmf_digit, signal_ptr, 1);
+			/* print debug info */
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "INFO DTMF(%c)\n", dtmf.digit);
 
-	/* queue it up */
-	switch_channel_queue_dtmf(channel, dtmf_digit);
+			/* Send 200 OK response */
+			nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
+	
+			return;
+		}
 
-	/* print debug info */
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "INFO DTMF(%s)\n", dtmf_digit);
+		if ((rec_header = sofia_glue_get_unknown_header(sip, "record"))) {
+			if (switch_strlen_zero(profile->record_template)) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Record attempted but no template defined.\n");
+				nua_respond(nh, 488, "Recording not enabled", NUTAG_WITH_THIS(nua), TAG_END());
+			} else {
+				if (!strcasecmp(rec_header, "on")) {
+					char *file;
 
-	/* Send 200 OK response */
-	nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
+					file = switch_channel_expand_variables(channel, profile->record_template);
+					switch_ivr_record_session(session, file, 0, NULL);
+					switch_channel_set_variable(channel, "sofia_record_file", file);
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Recording %s to %s\n", switch_channel_get_name(channel), file);
+					nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
+					if (file != profile->record_template) {
+						free(file);
+						file = NULL;
+					}
+				} else {
+					const char *file;
+
+					if ((file = switch_channel_get_variable(channel, "sofia_record_file"))) {
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Done recording %s to %s\n", switch_channel_get_name(channel), file);
+						switch_ivr_stop_record_session(session, file);
+						nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
+					} else {
+						nua_respond(nh, 488, "Nothing to stop", NUTAG_WITH_THIS(nua), TAG_END());
+					}
+				}
+			}
+
+			return;
+		}
+	}
 
-	return;
 }
 
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	Fri Dec 21 19:32:20 2007
@@ -347,6 +347,10 @@
 		tech_pvt->te = profile->te;
 	}
 
+	
+	tech_pvt->dtmf_type = profile->dtmf_type;
+
+
 	if (tech_pvt->bcng_pt) {
 		tech_pvt->cng_pt = tech_pvt->bcng_pt;
 	} else if (!tech_pvt->cng_pt) {
@@ -387,6 +391,20 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+
+const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name)
+{
+	sip_unknown_t *un;
+	for (un = sip->sip_unknown; un; un = un->un_next) {
+		if (!strcasecmp(un->un_name, name)) {
+			if (!switch_strlen_zero(un->un_value)) {
+				return un->un_value;
+			}
+		}
+	}
+	return NULL;
+}
+
 switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt)
 {
 	char *ip = tech_pvt->profile->rtpip;
@@ -1097,6 +1115,16 @@
 		flags |= SWITCH_RTP_FLAG_BUGGY_2833;
 	}
 
+	if ((val = switch_channel_get_variable(tech_pvt->channel, "dtmf_type"))) {
+		if (!strcasecmp(val, "rfc2833")) {
+			tech_pvt->dtmf_type = DTMF_2833;
+		} else if (!strcasecmp(val, "info")) {
+			tech_pvt->dtmf_type = DTMF_INFO;
+		} else {
+			tech_pvt->dtmf_type = tech_pvt->profile->dtmf_type;
+		}
+	}
+
 	if ((tech_pvt->profile->pflags & PFLAG_PASS_RFC2833)
 		|| ((val = switch_channel_get_variable(tech_pvt->channel, "pass_rfc2833")) && switch_true(val))) {
 		flags |= SWITCH_RTP_FLAG_PASS_RFC2833;

Modified: freeswitch/trunk/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c	Fri Dec 21 19:32:20 2007
@@ -810,7 +810,13 @@
 		teletone_dtmf_get(&tech_pvt->dtmf_detect, digit_str, sizeof(digit_str));
 	
 		if(digit_str[0]) {
-			switch_channel_queue_dtmf(channel, digit_str);
+			char *p = digit_str;
+			switch_dtmf_t dtmf = {0, globals.dtmf_on};
+			while(p && *p) {
+				dtmf.digit = *p;
+				switch_channel_queue_dtmf(channel, &dtmf);
+				p++;
+			}
 			if (globals.debug) {
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF DETECTED: [%s]\n", digit_str);
 			}
@@ -876,13 +882,12 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
-static switch_status_t wanpipe_send_dtmf(switch_core_session_t *session, char *digits)
+static switch_status_t wanpipe_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
 {
 	private_object_t *tech_pvt;
 	switch_channel_t *channel = NULL;
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
 	int wrote = 0;
-	char *cur = NULL;
 
 	channel = switch_core_session_get_channel(session);
 	assert(channel != NULL);
@@ -903,12 +908,13 @@
 			switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "SUCCESS!\n");
 		}
 	}
-	for (cur = digits; *cur; cur++) {
-		if ((wrote = teletone_mux_tones(&tech_pvt->tone_session, &tech_pvt->tone_session.TONES[(int)*cur]))) {
-			switch_buffer_write(tech_pvt->dtmf_buffer, tech_pvt->tone_session.buffer, wrote * 2);
-		}
+
+	tech_pvt->tone_session.duration = dtmf.duration * (tech_pvt->tone_session.rate / 1000);
+	if ((wrote = teletone_mux_tones(&tech_pvt->tone_session, &tech_pvt->tone_session.TONES[(int)dtmf->digit]))) {
+		switch_buffer_write(tech_pvt->dtmf_buffer, tech_pvt->tone_session.buffer, wrote * 2);
 	}
 
+
 	tech_pvt->skip_read_frames = 200;
 	
 	return status;

Modified: freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	(original)
+++ freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	Fri Dec 21 19:32:20 2007
@@ -1010,10 +1010,14 @@
 			return SWITCH_STATUS_FALSE;
 		}
 		break;
-	case SWITCH_INPUT_TYPE_DTMF:
-		dtmf = (char *) input;
-		argv[argc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(cb_state->cx, "dtmf"));
-		argv[argc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(cb_state->cx, dtmf));
+	case SWITCH_INPUT_TYPE_DTMF: 
+		{
+			switch_dtmf_t *_dtmf = (switch_dtmf_t *) input;
+			dtmf[0] = _dtmf->digit;
+			dtmf[1] = '\0';
+			argv[argc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(cb_state->cx, "dtmf"));
+			argv[argc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(cb_state->cx, dtmf));
+		}
 		break;
 	}
 
@@ -1208,8 +1212,6 @@
 static JSBool session_flush_digits(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
 {
 	struct js_session *jss = JS_GetPrivate(cx, obj);
-	char buf[256];
-	switch_size_t has;
 	switch_channel_t *channel;
 
 	METHOD_SANITY_CHECK();
@@ -1217,9 +1219,7 @@
 	channel = switch_core_session_get_channel(jss->session);
 	switch_assert(channel != NULL);
 
-	while ((has = switch_channel_has_dtmf(channel))) {
-		switch_channel_dequeue_dtmf(channel, buf, sizeof(buf));
-	}
+	switch_channel_flush_dtmf(channel);
 
 	*rval = BOOLEAN_TO_JSVAL(JS_TRUE);
 	return JS_TRUE;

Modified: freeswitch/trunk/src/mod/languages/mod_spidermonkey_teletone/mod_spidermonkey_teletone.c
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_spidermonkey_teletone/mod_spidermonkey_teletone.c	(original)
+++ freeswitch/trunk/src/mod/languages/mod_spidermonkey_teletone/mod_spidermonkey_teletone.c	Fri Dec 21 19:32:20 2007
@@ -257,7 +257,7 @@
 					uintN aargc = 0;
 					jsval aargv[4];
 
-					switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
+					switch_channel_dequeue_dtmf_string(channel, dtmf, sizeof(dtmf));
 					aargv[aargc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, dtmf));
 					JS_CallFunction(cx, obj, tto->function, aargc, aargv, &tto->ret);
 					ret = JS_GetStringBytes(JS_ValueToString(cx, tto->ret));

Modified: freeswitch/trunk/src/switch_channel.c
==============================================================================
--- freeswitch/trunk/src/switch_channel.c	(original)
+++ freeswitch/trunk/src/switch_channel.c	Fri Dec 21 19:32:20 2007
@@ -104,7 +104,7 @@
 
 struct switch_channel {
 	char *name;
-	switch_buffer_t *dtmf_buffer;
+	switch_queue_t *dtmf_queue;
 	switch_mutex_t *dtmf_mutex;
 	switch_mutex_t *flag_mutex;
 	switch_mutex_t *profile_mutex;
@@ -186,7 +186,7 @@
 	switch_event_create(&(*channel)->variables, SWITCH_EVENT_MESSAGE);
 	
 	switch_core_hash_init(&(*channel)->private_hash, pool);
-	switch_buffer_create_dynamic(&(*channel)->dtmf_buffer, 128, 128, 0);
+	switch_queue_create(&(*channel)->dtmf_queue, 128, pool);
 
 	switch_mutex_init(&(*channel)->dtmf_mutex, SWITCH_MUTEX_NESTED, pool);
 	switch_mutex_init(&(*channel)->flag_mutex, SWITCH_MUTEX_NESTED, pool);
@@ -203,18 +203,16 @@
 
 	switch_assert(channel != NULL);
 	switch_mutex_lock(channel->dtmf_mutex);
-	has = switch_buffer_inuse(channel->dtmf_buffer);
+	has = switch_queue_size(channel->dtmf_queue);
 	switch_mutex_unlock(channel->dtmf_mutex);
 
 	return has;
 }
 
-SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *channel, const char *dtmf)
+SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *channel, const switch_dtmf_t *dtmf)
 {
 	switch_status_t status;
-	register switch_size_t len, inuse;
-	switch_size_t wr = 0;
-	const char *p;
+	void *pop;
 
 	switch_assert(channel != NULL);
 
@@ -224,23 +222,24 @@
 		goto done;
 	}
 
-	inuse = switch_buffer_inuse(channel->dtmf_buffer);
-	len = strlen(dtmf);
-
-	if (len + inuse > switch_buffer_len(channel->dtmf_buffer)) {
-		switch_buffer_toss(channel->dtmf_buffer, strlen(dtmf));
-	}
-
-	p = dtmf;
-	while (wr < len && p) {
-		if (is_dtmf(*p)) {
-			wr++;
-		} else {
-			break;
+	if (is_dtmf(dtmf->digit)) {
+		switch_dtmf_t *dt;
+		int x = 0;
+
+		switch_zmalloc(dt, sizeof(*dt));
+		*dt = *dtmf;
+		while (switch_queue_trypush(channel->dtmf_queue, dt) != SWITCH_STATUS_SUCCESS) {
+			switch_queue_trypop(channel->dtmf_queue, &pop);
+			if (++x > 100) {
+				status = SWITCH_STATUS_FALSE;
+				free(dt);
+					goto done;
+			}
 		}
-		p++;
 	}
-	status = switch_buffer_write(channel->dtmf_buffer, dtmf, wr) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_MEMERR;
+	
+
+	status = SWITCH_STATUS_SUCCESS;
 
  done:
 
@@ -250,33 +249,64 @@
 }
 
 
-SWITCH_DECLARE(switch_size_t) switch_channel_dequeue_dtmf(switch_channel_t *channel, char *dtmf, switch_size_t len)
+SWITCH_DECLARE(switch_status_t) switch_channel_dequeue_dtmf(switch_channel_t *channel, switch_dtmf_t *dtmf)
 {
-	switch_size_t bytes;
 	switch_event_t *event;
+	void *pop;
+	switch_dtmf_t *dt;
+	switch_status_t status = SWITCH_STATUS_FALSE;
 
 	switch_assert(channel != NULL);
 
 	switch_mutex_lock(channel->dtmf_mutex);
-	if ((bytes = switch_buffer_read(channel->dtmf_buffer, dtmf, len)) > 0) {
-		*(dtmf + bytes) = '\0';
+
+	if (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
+		dt = (switch_dtmf_t *) pop;
+		*dtmf = *dt;
+		free(dt);
+		status = SWITCH_STATUS_SUCCESS;
 	}
 	switch_mutex_unlock(channel->dtmf_mutex);
-
-	if (bytes && switch_event_create(&event, SWITCH_EVENT_DTMF) == SWITCH_STATUS_SUCCESS) {
+	
+	if (status == SWITCH_STATUS_SUCCESS && 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-String", "%s", dtmf);
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Digit", "%c", dtmf->digit);
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Duration", "%u", dtmf->duration);
 		switch_event_fire(&event);
 	}
 
-	return bytes;
+	return status;
+
+}
 
+SWITCH_DECLARE(switch_size_t) switch_channel_dequeue_dtmf_string(switch_channel_t *channel, char *dtmf_str, switch_size_t len)
+{
+	switch_size_t x = 0;
+	switch_dtmf_t dtmf = {0};
+
+	memset(dtmf_str, 0, len);
+
+	while(x < len - 1 && switch_channel_dequeue_dtmf(channel, &dtmf) == SWITCH_STATUS_SUCCESS) {
+		dtmf_str[x++] = dtmf.digit;
+	}
+
+	return x;
+
+}
+
+SWITCH_DECLARE(void) switch_channel_flush_dtmf(switch_channel_t *channel)
+{
+	void *pop;
+	switch_mutex_lock(channel->dtmf_mutex);
+	while(switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
+		free(pop);
+	}
+	switch_mutex_unlock(channel->dtmf_mutex);
 }
 
 SWITCH_DECLARE(void) switch_channel_uninit(switch_channel_t *channel)
 {
 
-	switch_buffer_destroy(&channel->dtmf_buffer);
 	switch_core_hash_destroy(&channel->private_hash);
 	switch_event_destroy(&channel->variables);
 }

Modified: freeswitch/trunk/src/switch_core.c
==============================================================================
--- freeswitch/trunk/src/switch_core.c	(original)
+++ freeswitch/trunk/src/switch_core.c	Fri Dec 21 19:32:20 2007
@@ -145,9 +145,9 @@
 SWITCH_DECLARE(char *) switch_core_get_variable(const char *varname)
 {
 	char *val;
-	switch_mutex_lock(runtime.throttle_mutex);
+	switch_mutex_lock(runtime.global_mutex);
 	val = (char *) switch_core_hash_find(runtime.global_vars, varname);
-	switch_mutex_unlock(runtime.throttle_mutex);
+	switch_mutex_unlock(runtime.global_mutex);
 	return val;
 }
 
@@ -156,7 +156,7 @@
 	char *val;
 
 	if (varname) {
-		switch_mutex_lock(runtime.throttle_mutex);
+		switch_mutex_lock(runtime.global_mutex);
 		val = (char *) switch_core_hash_find(runtime.global_vars, varname);
 		if (val) {
 			free(val);
@@ -166,7 +166,7 @@
 		} else {
 			switch_core_hash_delete(runtime.global_vars, varname);
 		}
-		switch_mutex_unlock(runtime.throttle_mutex);
+		switch_mutex_unlock(runtime.global_mutex);
 	}
 }
 
@@ -671,6 +671,7 @@
 	}
 	switch_assert(runtime.memory_pool != NULL);
 	switch_mutex_init(&runtime.throttle_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
+	switch_mutex_init(&runtime.global_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
 	switch_core_set_globals();
 	switch_core_session_init(runtime.memory_pool);
 	switch_core_hash_init(&runtime.global_vars, runtime.memory_pool);

Modified: freeswitch/trunk/src/switch_core_io.c
==============================================================================
--- freeswitch/trunk/src/switch_core_io.c	(original)
+++ freeswitch/trunk/src/switch_core_io.c	Fri Dec 21 19:32:20 2007
@@ -881,7 +881,7 @@
 }
 
 
-SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_session_t *session, const char *dtmf)
+SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
 {
 	switch_io_event_hook_recv_dtmf_t *ptr;	
 	switch_status_t status;
@@ -894,7 +894,7 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
-SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_session_t *session, const char *dtmf)
+SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
 {
 	switch_io_event_hook_send_dtmf_t *ptr;
 	switch_status_t status = SWITCH_STATUS_FALSE;
@@ -907,28 +907,13 @@
 	}
 	
 	if (session->endpoint_interface->io_routines->send_dtmf) {
-		if (strchr(dtmf, 'w') || strchr(dtmf, 'W')) {
-			const char *d;
-			for (d = dtmf; d && *d; d++) {
-				char digit[2] = { 0 };
-
-				if (*d == 'w') {
-					switch_yield(500000);
-					continue;
-				} else if (*d == 'W') {
-					switch_yield(1000000);
-					continue;
-				}
-
-				digit[0] = *d;
-				if ((status = session->endpoint_interface->io_routines->send_dtmf(session, digit)) != SWITCH_STATUS_SUCCESS) {
-					return status;
-				}
-			}
+		if (dtmf->digit == 'w') {
+			switch_yield(500000);
+		} else if (dtmf->digit == 'W') {
+			switch_yield(1000000);
 		} else {
-			status = session->endpoint_interface->io_routines->send_dtmf(session, (char *)dtmf);
+			status = session->endpoint_interface->io_routines->send_dtmf(session, dtmf);
 		}
-
 	}
 
 	return status;

Modified: freeswitch/trunk/src/switch_core_session.c
==============================================================================
--- freeswitch/trunk/src/switch_core_session.c	(original)
+++ freeswitch/trunk/src/switch_core_session.c	Fri Dec 21 19:32:20 2007
@@ -565,7 +565,6 @@
 SWITCH_DECLARE(void) switch_core_session_reset(switch_core_session_t *session)
 {
 	switch_channel_t *channel;
-	char buf[256];
 	switch_size_t has;
 
 	/* clear resamplers*/
@@ -583,7 +582,7 @@
 	channel = switch_core_session_get_channel(session);
 
 	while ((has = switch_channel_has_dtmf(channel))) {
-		switch_channel_dequeue_dtmf(channel, buf, sizeof(buf));
+		switch_channel_flush_dtmf(channel);
 	}
 
 	switch_ivr_deactivate_unicast(session);

Modified: freeswitch/trunk/src/switch_cpp.cpp
==============================================================================
--- freeswitch/trunk/src/switch_cpp.cpp	(original)
+++ freeswitch/trunk/src/switch_cpp.cpp	Fri Dec 21 19:32:20 2007
@@ -398,9 +398,8 @@
 	channel = switch_core_session_get_channel(session);
 	assert(channel != NULL);
 
-	while ((has = switch_channel_has_dtmf(channel))) {
-		switch_channel_dequeue_dtmf(channel, buf, sizeof(buf));
-	}
+	switch_channel_flush_dtmf(channel);
+
 	return SWITCH_STATUS_SUCCESS;
 }
 

Modified: freeswitch/trunk/src/switch_ivr.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr.c	(original)
+++ freeswitch/trunk/src/switch_ivr.c	Fri Dec 21 19:32:20 2007
@@ -495,10 +495,10 @@
 			}
 
 			if (switch_channel_has_dtmf(channel)) {
-				char dtmf[128];
-				switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
+				switch_dtmf_t dtmf = {0};
+				switch_channel_dequeue_dtmf(channel, &dtmf);
 				if (args && args->input_callback) {
-					if ((status = args->input_callback(session, dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) {
+					if ((status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) {
 						break;
 					}
 				}
@@ -552,7 +552,7 @@
 	while (switch_channel_ready(channel)) {
 		switch_frame_t *read_frame;
 		switch_event_t *event;
-		char dtmf[128];
+		switch_dtmf_t dtmf = {0};
 
 		if (timeout) {
 			elapsed = (uint32_t) ((switch_time_now() - started) / 1000);
@@ -566,8 +566,8 @@
         }
 
 		if (switch_channel_has_dtmf(channel)) {
-			switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
-			status = args->input_callback(session, dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
+			switch_channel_dequeue_dtmf(channel, &dtmf);
+			status = args->input_callback(session, (void *)&dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
 		}
 
 		if (switch_core_session_dequeue_event(session, &event) == SWITCH_STATUS_SUCCESS) {
@@ -639,17 +639,20 @@
         }
 
 		if (switch_channel_has_dtmf(channel)) {
-			char dtmf[128];
-
-			switch_channel_dequeue_dtmf(channel, dtmf, maxdigits);
-			for (i = 0; i < strlen(dtmf); i++) {
+			switch_dtmf_t dtmf = {0};
+			int y;
+			
+			for (y = 0; y < maxdigits; y++) {
+				if (switch_channel_dequeue_dtmf(channel, &dtmf) != SWITCH_STATUS_SUCCESS) {
+					break;
+				}
 
-				if (!switch_strlen_zero(terminators) && strchr(terminators, dtmf[i]) && terminator != NULL) {
-					*terminator = dtmf[i];
+				if (!switch_strlen_zero(terminators) && strchr(terminators, dtmf.digit) && terminator != NULL) {
+					*terminator = dtmf.digit;
 					return SWITCH_STATUS_SUCCESS;
 				}
 
-				buf[x++] = dtmf[i];
+				buf[x++] = dtmf.digit;
 				buf[x] = '\0';
 				if (x >= buflen || x >= maxdigits) {
 					return SWITCH_STATUS_SUCCESS;

Modified: freeswitch/trunk/src/switch_ivr_async.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_async.c	(original)
+++ freeswitch/trunk/src/switch_ivr_async.c	Fri Dec 21 19:32:20 2007
@@ -481,9 +481,9 @@
 			}
 
 			if ((flags & ED_DTMF) && switch_channel_has_dtmf(channel)) {
-				char dtmf[128] = "";
-				switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
-				fcommand = dtmf;
+				switch_dtmf_t dtmf = {0};
+				switch_channel_dequeue_dtmf(channel, &dtmf);
+				*fcommand = dtmf.digit;
 			}
 
 			if (fcommand) {
@@ -717,7 +717,14 @@
 			teletone_dtmf_detect(&pvt->dtmf_detect, frame.data, frame.samples);
 			teletone_dtmf_get(&pvt->dtmf_detect, digit_str, sizeof(digit_str));
 			if (digit_str[0]) {
-				switch_channel_queue_dtmf(channel, digit_str);
+				char *p = digit_str;
+				while(p && *p) {
+					switch_dtmf_t dtmf;
+					dtmf.digit = *p;
+					dtmf.duration = SWITCH_DEFAULT_DTMF_DURATION;
+					switch_channel_queue_dtmf(channel, &dtmf);
+					p++;
+				}
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF DETECTED: [%s]\n", digit_str);
 			}
 		}
@@ -804,7 +811,7 @@
 }
 
 
-static switch_status_t generate_on_dtmf(switch_core_session_t *session, const char *dtmf)
+static switch_status_t generate_on_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
 {
 
     switch_media_bug_t *bug;
@@ -815,7 +822,9 @@
         
         if (pvt) {
 			switch_mutex_lock(pvt->mutex);
-			teletone_run(&pvt->ts, (char *)dtmf);
+			char buf[2] = "";
+			buf[0] = dtmf->digit;
+			teletone_run(&pvt->ts, buf);
 			switch_mutex_unlock(pvt->mutex);
 			return SWITCH_STATUS_FALSE;
 		}

Modified: freeswitch/trunk/src/switch_ivr_bridge.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_bridge.c	(original)
+++ freeswitch/trunk/src/switch_ivr_bridge.c	Fri Dec 21 19:32:20 2007
@@ -116,17 +116,20 @@
 		}
 
 		/* if 1 channel has DTMF pass it to the other */
-		if (switch_channel_has_dtmf(chan_a)) {
-			char dtmf[128];
-			switch_channel_dequeue_dtmf(chan_a, dtmf, sizeof(dtmf));
-			if (input_callback) {
-				if (input_callback(session_a, dtmf, SWITCH_INPUT_TYPE_DTMF, user_data, 0) != SWITCH_STATUS_SUCCESS) {
-					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s ended call via DTMF\n", switch_channel_get_name(chan_a));
-					switch_core_session_kill_channel(session_b, SWITCH_SIG_BREAK);
-					break;
+		while (switch_channel_has_dtmf(chan_a)) {
+			switch_dtmf_t dtmf = { 0, 0 };
+			if (switch_channel_dequeue_dtmf(chan_a, &dtmf) == SWITCH_STATUS_SUCCESS) {
+				if (input_callback) {
+					if (input_callback(session_a, (void *)&dtmf, SWITCH_INPUT_TYPE_DTMF, user_data, 0) != SWITCH_STATUS_SUCCESS) {
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s ended call via DTMF\n", switch_channel_get_name(chan_a));
+						switch_core_session_kill_channel(session_b, SWITCH_SIG_BREAK);
+						break;
+					}
 				}
+				
+
+				switch_core_session_send_dtmf(session_b, &dtmf);
 			}
-			switch_core_session_send_dtmf(session_b, dtmf);
 		}
 
 		if (switch_core_session_dequeue_event(session_a, &event) == SWITCH_STATUS_SUCCESS) {

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	Fri Dec 21 19:32:20 2007
@@ -338,7 +338,7 @@
 													   switch_file_handle_t *fh, char *file, switch_input_args_t *args, uint32_t limit)
 {
 	switch_channel_t *channel;
-	char dtmf[128];
+	switch_dtmf_t dtmf = {0};
 	switch_file_handle_t lfh = { 0 };
 	switch_frame_t *read_frame;
 	switch_codec_t codec, *read_codec;
@@ -476,11 +476,11 @@
 					status = SWITCH_STATUS_BREAK;
 					break;
 				}
-				switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
+				switch_channel_dequeue_dtmf(channel, &dtmf);
 				if (args->input_callback) {
-					status = args->input_callback(session, dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
+					status = args->input_callback(session, (void *)&dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
 				} else {
-					switch_copy_string((char *) args->buf, dtmf, args->buflen);
+					switch_copy_string((char *) args->buf, (void *)&dtmf, args->buflen);
 					status = SWITCH_STATUS_BREAK;
 				}
 			}
@@ -664,7 +664,7 @@
 {
 	switch_channel_t *channel;
 	int16_t *abuf;
-	char dtmf[128];
+	switch_dtmf_t dtmf = {0};
 	uint32_t interval = 0, samples = 0, framelen, sample_start = 0;
 	uint32_t ilen = 0;
 	switch_size_t olen = 0, llen = 0;
@@ -900,11 +900,11 @@
 					done = 1;
 					break;
 				}
-				switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
+				switch_channel_dequeue_dtmf(channel, &dtmf);
 				if (args->input_callback) {
-					status = args->input_callback(session, dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
+					status = args->input_callback(session, (void *)&dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
 				} else {
-					switch_copy_string((char *) args->buf, dtmf, args->buflen);
+					switch_copy_string((char *) args->buf, (void *)&dtmf, args->buflen);
 					status = SWITCH_STATUS_BREAK;
 				}
 			}
@@ -1227,7 +1227,7 @@
 {
 	switch_channel_t *channel;
 	short abuf[960];
-	char dtmf[128];
+	switch_dtmf_t dtmf = {0};
 	uint32_t len = 0;
 	switch_size_t ilen = 0;
 	switch_frame_t write_frame = { 0 };
@@ -1357,11 +1357,11 @@
 				if (args->buf && !strcasecmp(args->buf, "_break_")) {
 					status = SWITCH_STATUS_BREAK;
 				} else {
-					switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
+					switch_channel_dequeue_dtmf(channel, &dtmf);
 					if (args->input_callback) {
-						status = args->input_callback(session, dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
+						status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen);
 					} else {
-						switch_copy_string((char *) args->buf, dtmf, args->buflen);
+						switch_copy_string((char *) args->buf, (void *) &dtmf, args->buflen);
 						status = SWITCH_STATUS_BREAK;
 					}
 				}

Modified: freeswitch/trunk/src/switch_rtp.c
==============================================================================
--- freeswitch/trunk/src/switch_rtp.c	(original)
+++ freeswitch/trunk/src/switch_rtp.c	Fri Dec 21 19:32:20 2007
@@ -75,11 +75,6 @@
 } rtp_msg_t;
 
 
-struct rfc2833_digit {
-	char digit;
-	int duration;
-};
-
 struct switch_rtp_vad_data {
 	switch_core_session_t *session;
 	switch_codec_t vad_codec;
@@ -115,7 +110,7 @@
 	char last_digit;
 	unsigned int dc;
 	time_t last_digit_time;
-	switch_buffer_t *dtmf_buffer;
+	switch_queue_t *dtmf_inqueue;
 	switch_mutex_t *dtmf_mutex;
 };
 
@@ -497,7 +492,9 @@
 
 	switch_mutex_init(&rtp_session->flag_mutex, SWITCH_MUTEX_NESTED, pool);
 	switch_mutex_init(&rtp_session->dtmf_data.dtmf_mutex, SWITCH_MUTEX_NESTED, pool);
-	switch_buffer_create_dynamic(&rtp_session->dtmf_data.dtmf_buffer, 128, 128, 0);
+	switch_queue_create(&rtp_session->dtmf_data.dtmf_queue, 100, rtp_session->pool);
+	switch_queue_create(&rtp_session->dtmf_data.dtmf_inqueue, 100, rtp_session->pool);
+
 	switch_rtp_set_flag(rtp_session, flags);
 
 	/* for from address on recvfrom calls */
@@ -696,11 +693,20 @@
 
 SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
 {
+	void *pop;
+
 	if (!switch_rtp_ready(*rtp_session)) {
 		return;
 	}
 
-
+	while(switch_queue_trypop((*rtp_session)->dtmf_data.dtmf_inqueue, &pop) == SWITCH_STATUS_SUCCESS) {
+		free(pop);
+	}
+	
+	while(switch_queue_trypop((*rtp_session)->dtmf_data.dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
+		free(pop);
+	}
+	
 	(*rtp_session)->ready = 0;
 
 	switch_mutex_lock((*rtp_session)->flag_mutex);
@@ -709,10 +715,6 @@
 		stfu_n_destroy(&(*rtp_session)->jb);
 	}
 
-	if ((*rtp_session)->dtmf_data.dtmf_buffer) {
-		switch_buffer_destroy(&(*rtp_session)->dtmf_data.dtmf_buffer);
-	}
-
 	switch_rtp_kill_socket(*rtp_session);
 	switch_socket_close((*rtp_session)->sock);
 	(*rtp_session)->sock = NULL;
@@ -834,7 +836,7 @@
 
 		if (switch_queue_trypop(rtp_session->dtmf_data.dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
 			int x;
-			struct rfc2833_digit *rdigit = pop;
+			switch_dtmf_t *rdigit = pop;
 
 			memset(rtp_session->dtmf_data.out_digit_packet, 0, 4);
 			rtp_session->dtmf_data.out_digit_sofar = 0;
@@ -1078,9 +1080,9 @@
 				rtp_session->dtmf_data.in_digit_seq = in_digit_seq;
 				if (duration && end) {
 					if (key != rtp_session->dtmf_data.last_digit) {
-						char digit_str[] = { key, 0 };
+						switch_dtmf_t dtmf = { key, duration };
 						time(&rtp_session->dtmf_data.last_digit_time);
-						switch_rtp_queue_dtmf(rtp_session, digit_str);
+						switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
 						switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK);
 					}
 					if (++rtp_session->dtmf_data.dc >= 3) {
@@ -1126,92 +1128,72 @@
 
 	if (switch_rtp_ready(rtp_session)) {
 		switch_mutex_lock(rtp_session->dtmf_data.dtmf_mutex);
-		has = switch_buffer_inuse(rtp_session->dtmf_data.dtmf_buffer);
+		has = switch_queue_size(rtp_session->dtmf_data.dtmf_inqueue);
 		switch_mutex_unlock(rtp_session->dtmf_data.dtmf_mutex);
 	}
 
 	return has;
 }
 
-SWITCH_DECLARE(switch_status_t) switch_rtp_queue_dtmf(switch_rtp_t *rtp_session, char *dtmf)
-{
-	switch_status_t status;
-	register switch_size_t len, inuse;
-	switch_size_t wr = 0;
-	char *p;
 
+SWITCH_DECLARE(switch_size_t) switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session, switch_dtmf_t *dtmf)
+{
+	switch_size_t bytes = 0;
+	switch_dtmf_t *_dtmf = NULL;
+	void *pop;
+	
 	if (!switch_rtp_ready(rtp_session)) {
-		return SWITCH_STATUS_FALSE;
+		return bytes;
 	}
 
 	switch_mutex_lock(rtp_session->dtmf_data.dtmf_mutex);
-
-	inuse = switch_buffer_inuse(rtp_session->dtmf_data.dtmf_buffer);
-	len = strlen(dtmf);
-
-	if (len + inuse > switch_buffer_len(rtp_session->dtmf_data.dtmf_buffer)) {
-		switch_buffer_toss(rtp_session->dtmf_data.dtmf_buffer, strlen(dtmf));
+	if (switch_queue_trypop(rtp_session->dtmf_data.dtmf_inqueue, &pop) == SWITCH_STATUS_SUCCESS) {
+		_dtmf = (switch_dtmf_t *) pop;
+		*dtmf = *_dtmf;
+		bytes++;
 	}
-
-	p = dtmf;
-	while (wr < len && p) {
-		if (is_dtmf(*p)) {
-			wr++;
-		} else {
-			break;
-		}
-		p++;
-	}
-
-	status = switch_buffer_write(rtp_session->dtmf_data.dtmf_buffer, dtmf, wr) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_MEMERR;
 	switch_mutex_unlock(rtp_session->dtmf_data.dtmf_mutex);
 
-	return status;
+	return bytes;
 }
 
 
-SWITCH_DECLARE(switch_size_t) switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session, char *dtmf, switch_size_t len)
+SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_session, const switch_dtmf_t *dtmf)
 {
-	switch_size_t bytes = 0;
+
+	switch_dtmf_t *rdigit;
 
 	if (!switch_rtp_ready(rtp_session)) {
-		return bytes;
+		return SWITCH_STATUS_FALSE;
 	}
 
-	switch_mutex_lock(rtp_session->dtmf_data.dtmf_mutex);
-	if ((bytes = switch_buffer_read(rtp_session->dtmf_data.dtmf_buffer, dtmf, len)) > 0) {
-		*(dtmf + bytes) = '\0';
+	if ((rdigit = malloc(sizeof(*rdigit))) != 0) {
+		*rdigit = *dtmf;
+		switch_queue_push(rtp_session->dtmf_data.dtmf_queue, rdigit);
+	} else {
+		abort();
 	}
-	switch_mutex_unlock(rtp_session->dtmf_data.dtmf_mutex);
-
-	return bytes;
+	
+	return SWITCH_STATUS_SUCCESS;
 }
 
 
-SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_session, char *digits, uint32_t duration)
+SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833_in(switch_rtp_t *rtp_session, const switch_dtmf_t *dtmf)
 {
-	char *c;
+
+	switch_dtmf_t *rdigit;
 
 	if (!switch_rtp_ready(rtp_session)) {
 		return SWITCH_STATUS_FALSE;
 	}
 
-	if (!rtp_session->dtmf_data.dtmf_queue) {
-		switch_queue_create(&rtp_session->dtmf_data.dtmf_queue, 100, rtp_session->pool);
-	}
-
-	for (c = digits; *c; c++) {
-		struct rfc2833_digit *rdigit;
-
-		if ((rdigit = malloc(sizeof(*rdigit))) != 0) {
-			memset(rdigit, 0, sizeof(*rdigit));
-			rdigit->digit = *c;
-			rdigit->duration = duration;
-			switch_queue_push(rtp_session->dtmf_data.dtmf_queue, rdigit);
-		} else {
-			return SWITCH_STATUS_MEMERR;
-		}
+	if ((rdigit = malloc(sizeof(*rdigit))) != 0) {
+		*rdigit = *dtmf;
+		switch_queue_push(rtp_session->dtmf_data.dtmf_inqueue, rdigit);
+	} else {
+		abort();
 	}
+	
 	return SWITCH_STATUS_SUCCESS;
 }
 



More information about the Freeswitch-trunk mailing list