]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
dtmf overhaul testers wanted
authorAnthony Minessale <anthony.minessale@gmail.com>
Sat, 22 Dec 2007 00:32:20 +0000 (00:32 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Sat, 22 Dec 2007 00:32:20 +0000 (00:32 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6952 d0543943-73ff-0310-b7d9-9358b9ac24b2

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

index 460bb01d83db85d94e06dedfb733472a12143aa4..deaa34a9549b56f094de25772299b77927e579ef 100644 (file)
@@ -168,6 +168,7 @@ struct switch_runtime {
        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;
index 7cd448196df40c7e8da9f8ed8135593a578d6d57..40ccb7db57c2af9945416045d57e13f3c792bff0 100644 (file)
@@ -422,19 +422,20 @@ SWITCH_DECLARE(switch_size_t) switch_channel_has_dtmf(switch_channel_t *channel)
 /*!
   \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
index d6e034d5804a0071ccb99684990e4208bb9effa7..f4dd995873dd6fa3aea8c17d80b0d660b3996903 100644 (file)
@@ -829,7 +829,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_waitfor_write(switch_core_se
   \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 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_sessio
   \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);
 
 ///\}
 
index 0e2f5751b37a3e0a16f0a73b23696ecf777a0524..41021c6218c5924c9be9ee3855c69e5caeda5ac6 100644 (file)
@@ -59,8 +59,8 @@ typedef switch_status_t (*switch_video_write_frame_hook_t) (switch_core_session_
 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 *);
 
 
index b5e4ed9a5534d2944b3c364e0f5165d7d94a4288..ebdda1abf42990b2df2e29fc72330d7d1ba06248 100644 (file)
@@ -105,7 +105,7 @@ typedef switch_status_t (*switch_io_write_frame_t) (switch_core_session_t *, swi
 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 *);
index 92b5386fd8dbb566fd0fe778fcb756292552590f..c22ff8b0b426c75a57d28e5b365f21cecdb8b280 100644 (file)
@@ -261,7 +261,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_read(switch_rtp_t *rtp_session, void
   \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
@@ -270,22 +271,13 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833(switch_rtp_t *rtp_sessi
 */
 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
index 3969165f0b65955d1bb2dee1e4d0125c81a0bb11..2206eaaf55a9d25ad345368e169dc48bdef8ad9f 100644 (file)
@@ -92,7 +92,7 @@ SWITCH_BEGIN_EXTERN_C
 #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 @@ SWITCH_BEGIN_EXTERN_C
 #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),
index 0796847e57c5aff64f77b8952c24438caea9a794..673fa5c12c3fe6f199a4e721dc10c47ed14582b9 100644 (file)
@@ -1648,7 +1648,7 @@ static void conference_loop_output(conference_member_t * member)
 
                /* 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 @@ static switch_status_t conf_api_sub_dtmf(conference_member_t * member, switch_st
 {
        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 @@ static switch_status_t conf_api_sub_dtmf(conference_member_t * member, switch_st
 
        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);
index 729ab57b1edd111f9f6391e2a6b215ee19cfb20d..8df5cc93b26975434dccbe832190dfa56f7dbeec 100644 (file)
@@ -193,10 +193,17 @@ SWITCH_STANDARD_APP(break_function)
 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 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit
        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 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit
                        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;
                                }
                        }
                }
index e0641b1de9d7f2ecb77688f9d578f9cdb65c0f8b..f815f354bc82264631551e529a698c7ddc9def31 100644 (file)
@@ -48,8 +48,9 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit
        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);
index cbdcfb0601fe2a58a0e0b7f50b4aaa079d661107..3d97f78e2c004377c3b1d7902e4c628cc48091e2 100644 (file)
@@ -91,11 +91,11 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit
 {
        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;
index c62a8738c65673c835b89440b79c97e82a4494b1..0909b2641d09a407400483e155b8cefdc585fe04 100644 (file)
@@ -615,9 +615,11 @@ static switch_status_t cancel_on_dtmf(switch_core_session_t *session, void *inpu
        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 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in
        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 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in
                 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 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in
                 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;
index e1b2bd17116f6a5a031813461a0feb07c387ce2a..1c43d1cc8b80fe7a62537448340bea430ff7c39a 100644 (file)
@@ -522,14 +522,14 @@ static switch_status_t channel_waitfor_write(switch_core_session_t *session, int
 
 }
 
-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 engage_device(unsigned int sample_rate, int codec_ms)
 
 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);
        }
index eec909d09b75491d2be261b2517f2de4ff77fed6..b5e4ba54773639d17cef1419bd732bab98edae40 100644 (file)
@@ -1344,7 +1344,7 @@ static switch_status_t channel_send_dtmf(switch_core_session_t *session, char *d
 
        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 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
                        }
 #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 @@ static ldl_status handle_signalling(ldl_handle_t * handle, ldl_session_t * dlses
        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);
index 650f59228dc068eb87051e98c30471057ecea986..a913e72521d2466848143f489ebc0a9253daf917 100644 (file)
@@ -620,17 +620,14 @@ static switch_status_t channel_waitfor_write(switch_core_session_t *session, int
 
 }
 
-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 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_iax_runtime)
                                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;
index 1ad69c5581d8820d30d8c10bc65ee27eaadec2d1..8b5590bb1c8fe15f096d29ac2855d611e6123cf9 100644 (file)
@@ -524,14 +524,14 @@ static switch_status_t channel_waitfor_write(switch_core_session_t *session, int
 
 }
 
-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 engage_ring_device(int sample_rate, int channels)
 
 
 
-
 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);
        }
index c9e960b3b01f7ec1faed756ce65d846d8b00ddfb..67ec48680ba2390545e91917a5e910a7a9bf88d9 100644 (file)
@@ -540,9 +540,9 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
                        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 @@ static switch_status_t sofia_waitfor_write(switch_core_session_t *session, int m
        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)
index 868db83c5c50994502254596032c27018ef8ee6d..9f65d23c5276fdf522a67be9bea71d6b3a18acc6 100644 (file)
@@ -83,6 +83,13 @@ typedef struct private_object private_object_t;
 #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 @@ struct sofia_profile {
        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 @@ struct private_object {
        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 @@ sofia_transport_t sofia_glue_url2transport(const url_t *url);
 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);
index 486a1e70bce4a68a5768ff4e84aca5bb17984e64..b2603d4a979d1c6e82981082b3ba0a8c2fa7e717 100644 (file)
@@ -884,6 +884,16 @@ switch_status_t config_sofia(int reload, char *profile_name)
 
                                        } 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 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
 {
        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=");
-
-       /* 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;
-       }
+       if (session) {
+               /* Get the channel */
+               channel = switch_core_session_get_channel(session);
 
-       /* Get the channel */
-       channel = switch_core_session_get_channel(session);
+               /* 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);
 
-       /* 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);
+               if (sip && sip->sip_payload && sip->sip_payload->pl_data) {
+                       switch_dtmf_t dtmf = { 0, SWITCH_DEFAULT_DTMF_DURATION };
 
-       /* Barf if we didn't get it */
-       switch_assert(tech_pvt != NULL);
+                       /* 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;
+                       }
 
-       /* move signal_ptr where we need it (right past Signal=) */
-       signal_ptr = signal_ptr + 7;
+                       /* 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;
+                       }
 
-       /* put the digit somewhere we can muck with */
-       strncpy(dtmf_digit, signal_ptr, 1);
+                       
+                       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;
+                       }
+
+                       /* queue it up */
+                       switch_channel_queue_dtmf(channel, &dtmf);
 
-       /* queue it up */
-       switch_channel_queue_dtmf(channel, dtmf_digit);
+                       /* print debug info */
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "INFO DTMF(%c)\n", dtmf.digit);
 
-       /* print debug info */
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "INFO DTMF(%s)\n", dtmf_digit);
+                       /* Send 200 OK response */
+                       nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
+       
+                       return;
+               }
 
-       /* Send 200 OK response */
-       nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
+               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;
+
+                                       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;
 }
 
 
index 96dabba8aa82a4ca4da9ceef248f356c4aa3b7d8..e92ca267b78580bb454c3bdcb53089995067cd7b 100644 (file)
@@ -347,6 +347,10 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t *
                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 @@ switch_status_t sofia_glue_ext_address_lookup(char **ip, switch_port_t *port, ch
        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 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
                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;
index 38125acf0c95cdeb9a0e07dfe5c11cb9385aa8d5..298ef565e37fced63b9dec4093766f31ad047bd0 100644 (file)
@@ -810,7 +810,13 @@ static switch_status_t wanpipe_read_frame(switch_core_session_t *session, switch
                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 @@ static switch_status_t wanpipe_write_frame(switch_core_session_t *session, switc
        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 @@ static switch_status_t wanpipe_send_dtmf(switch_core_session_t *session, char *d
                        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;
index 7f76b3dfc7606b6cf586753e3a3bb3ff4723ff3a..b556303a403bb44110bac4ee893e58b6be94075b 100644 (file)
@@ -1010,10 +1010,14 @@ static switch_status_t js_common_callback(switch_core_session_t *session, void *
                        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 switch_status_t js_collect_input_callback(switch_core_session_t *session,
 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 @@ static JSBool session_flush_digits(JSContext * cx, JSObject * obj, uintN argc, j
        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;
index 11cb13e1cd8741ca3ca9051c35bf36ad06740624..df3dcbb7d80073cae321a2074b0b6a2605d0aba0 100644 (file)
@@ -257,7 +257,7 @@ static JSBool teletone_generate(JSContext * cx, JSObject * obj, uintN argc, jsva
                                        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));
index 41f357df32f78ca6aa7f59faca3b40a4365bda0d..5b94afe596be2f64211770ab6ea012503ebb3b4c 100644 (file)
@@ -104,7 +104,7 @@ static struct switch_cause_table CAUSE_CHART[] = {
 
 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_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel,
        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_DECLARE(switch_size_t) switch_channel_has_dtmf(switch_channel_t *channel)
 
        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 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *chan
                goto done;
        }
 
-       inuse = switch_buffer_inuse(channel->dtmf_buffer);
-       len = strlen(dtmf);
+       if (is_dtmf(dtmf->digit)) {
+               switch_dtmf_t *dt;
+               int x = 0;
 
-       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;
+               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_status_t) switch_channel_queue_dtmf(switch_channel_t *chan
 }
 
 
-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);
 }
index 605d37207e1c0a3eebcad7e6495493f4b65d0bc2..aeeadac010652538900cf64967fd0a157ffc29eb 100644 (file)
@@ -145,9 +145,9 @@ SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handl
 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 @@ SWITCH_DECLARE(void) switch_core_set_variable(const char *varname, const char *v
        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 @@ SWITCH_DECLARE(void) switch_core_set_variable(const char *varname, const char *v
                } 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_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
        }
        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);
index a5281f5d1789df2c133928dd6512d6c7c8714480..29a404d02460902081a9cf2c17666f5335e336ce 100644 (file)
@@ -881,7 +881,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_waitfor_write(switch_core_se
 }
 
 
-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 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_sessio
        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 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_sessio
        }
        
        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;
index 1cc88bc773676921800387428661680260ab7d3d..b57318411aabc5bd67f25c92b7da284f967a922d 100644 (file)
@@ -565,7 +565,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_private_event(switch
 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 @@ SWITCH_DECLARE(void) switch_core_session_reset(switch_core_session_t *session)
        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);
index 038a0a27018ca58f1714e815525cad16c16892d3..ae29c36bd97d7e11a198d941284e48655dc82fca 100644 (file)
@@ -398,9 +398,8 @@ int CoreSession::flushDigits()
        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;
 }
 
index b2b3c5d6b8f1d45b41527ead8d0edd5adcb9f05d..f96fc6e93b6c1a026aaebcaa61c3a9edead54137 100644 (file)
@@ -495,10 +495,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session,
                        }
 
                        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 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_s
        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 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_s
         }
 
                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 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_sess
         }
 
                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;
index c12b03620eaa22e343035c86db6c9e478dd11251..9a36d65213d3224d341063cdfdc2de308b503cf2 100644 (file)
@@ -481,9 +481,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
                        }
 
                        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 @@ static switch_bool_t inband_dtmf_callback(switch_media_bug_t *bug, void *user_da
                        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 int teletone_dtmf_generate_handler(teletone_generation_session_t * ts, te
 }
 
 
-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 @@ static switch_status_t generate_on_dtmf(switch_core_session_t *session, const ch
         
         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;
                }
index 236b1ee5c7a5665fbcde8069e8c70846188592d3..1a3457d8a3199109407ed0872d41643389341e3e 100644 (file)
@@ -116,17 +116,20 @@ static void *audio_bridge_thread(switch_thread_t * thread, void *obj)
                }
 
                /* 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) {
index 254b4fe1933ec1cecc660eb15006d9224a1f1614..51f3b01d9d86826025b74470b98def3ccdb35cd9 100644 (file)
@@ -338,7 +338,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
                                                                                                           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 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
                                        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_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
 {
        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 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
                                        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_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
 {
        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 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
                                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;
                                        }
                                }
index 5fd76cc45dab39541975b62604ca65b5ead5aac4..2792feb3ba51213caa596cc3b1581ca310110807 100644 (file)
@@ -75,11 +75,6 @@ typedef struct {
 } 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 @@ struct switch_rtp_rfc2833_data {
        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_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
 
        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(uint8_t) switch_rtp_ready(switch_rtp_t *rtp_session)
 
 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 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
                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 @@ static void do_2833(switch_rtp_t *rtp_session)
 
                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 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
                                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 @@ SWITCH_DECLARE(switch_size_t) switch_rtp_has_dtmf(switch_rtp_t *rtp_session)
 
        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;
 }