From 2931fc9109b60f68d25b533c86ad44113dbe7f20 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 22 Dec 2007 00:32:20 +0000 Subject: [PATCH] dtmf overhaul testers wanted git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6952 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/private/switch_core_pvt.h | 1 + src/include/switch_channel.h | 11 +- src/include/switch_core.h | 4 +- src/include/switch_core_event_hook.h | 4 +- src/include/switch_module_interfaces.h | 2 +- src/include/switch_rtp.h | 16 +- src/include/switch_types.h | 7 +- .../mod_conference/mod_conference.c | 14 +- .../applications/mod_dptools/mod_dptools.c | 20 ++- src/mod/applications/mod_fifo/mod_fifo.c | 5 +- src/mod/applications/mod_rss/mod_rss.c | 4 +- .../mod_voicemail/mod_voicemail.c | 20 +-- src/mod/endpoints/mod_alsa/mod_alsa.c | 18 ++- .../endpoints/mod_dingaling/mod_dingaling.c | 16 +- src/mod/endpoints/mod_iax/mod_iax.c | 16 +- .../endpoints/mod_portaudio/mod_portaudio.c | 19 ++- src/mod/endpoints/mod_sofia/mod_sofia.c | 28 +++- src/mod/endpoints/mod_sofia/mod_sofia.h | 11 ++ src/mod/endpoints/mod_sofia/sofia.c | 149 ++++++++++++------ src/mod/endpoints/mod_sofia/sofia_glue.c | 28 ++++ src/mod/endpoints/mod_wanpipe/mod_wanpipe.c | 20 ++- .../mod_spidermonkey/mod_spidermonkey.c | 18 +-- .../mod_spidermonkey_teletone.c | 2 +- src/switch_channel.c | 90 +++++++---- src/switch_core.c | 9 +- src/switch_core_io.c | 29 +--- src/switch_core_session.c | 3 +- src/switch_cpp.cpp | 5 +- src/switch_ivr.c | 29 ++-- src/switch_ivr_async.c | 21 ++- src/switch_ivr_bridge.c | 21 +-- src/switch_ivr_play_say.c | 24 +-- src/switch_rtp.c | 124 +++++++-------- 33 files changed, 475 insertions(+), 313 deletions(-) diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 460bb01d83..deaa34a954 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -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; diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 7cd448196d..40ccb7db57 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -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 diff --git a/src/include/switch_core.h b/src/include/switch_core.h index d6e034d580..f4dd995873 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -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); ///\} diff --git a/src/include/switch_core_event_hook.h b/src/include/switch_core_event_hook.h index 0e2f5751b3..41021c6218 100644 --- a/src/include/switch_core_event_hook.h +++ b/src/include/switch_core_event_hook.h @@ -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 *); diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index b5e4ed9a55..ebdda1abf4 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -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 *); diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index 92b5386fd8..c22ff8b0b4 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -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 diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 3969165f0b..2206eaaf55 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -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), diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 0796847e57..673fa5c12c 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -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); diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 729ab57b1e..8df5cc93b2 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -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; } } } diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index e0641b1de9..f815f354bc 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -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); diff --git a/src/mod/applications/mod_rss/mod_rss.c b/src/mod/applications/mod_rss/mod_rss.c index cbdcfb0601..3d97f78e2c 100644 --- a/src/mod/applications/mod_rss/mod_rss.c +++ b/src/mod/applications/mod_rss/mod_rss.c @@ -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; diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index c62a8738c6..0909b2641d 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -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; diff --git a/src/mod/endpoints/mod_alsa/mod_alsa.c b/src/mod/endpoints/mod_alsa/mod_alsa.c index e1b2bd1711..1c43d1cc8b 100644 --- a/src/mod/endpoints/mod_alsa/mod_alsa.c +++ b/src/mod/endpoints/mod_alsa/mod_alsa.c @@ -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); } diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index eec909d09b..b5e4ba5477 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -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); diff --git a/src/mod/endpoints/mod_iax/mod_iax.c b/src/mod/endpoints/mod_iax/mod_iax.c index 650f59228d..a913e72521 100644 --- a/src/mod/endpoints/mod_iax/mod_iax.c +++ b/src/mod/endpoints/mod_iax/mod_iax.c @@ -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; diff --git a/src/mod/endpoints/mod_portaudio/mod_portaudio.c b/src/mod/endpoints/mod_portaudio/mod_portaudio.c index 1ad69c5581..8b5590bb1c 100644 --- a/src/mod/endpoints/mod_portaudio/mod_portaudio.c +++ b/src/mod/endpoints/mod_portaudio/mod_portaudio.c @@ -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); } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index c9e960b3b0..67ec48680b 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -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) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 868db83c5c..9f65d23c52 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -83,6 +83,13 @@ typedef struct private_object private_object_t; #include #include + +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); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 486a1e70bc..b2603d4a97 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -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="); + 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; + /* 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); - /* 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 (sip && sip->sip_payload && sip->sip_payload->pl_data) { + switch_dtmf_t dtmf = { 0, SWITCH_DEFAULT_DTMF_DURATION }; + + /* 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; + } + + + 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); + + /* print debug info */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "INFO DTMF(%c)\n", dtmf.digit); + + /* Send 200 OK response */ + nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END()); + + return; + } + + 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; + } } - /* 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); - - /* move signal_ptr where we need it (right past Signal=) */ - signal_ptr = signal_ptr + 7; - - /* put the digit somewhere we can muck with */ - strncpy(dtmf_digit, signal_ptr, 1); - - /* queue it up */ - switch_channel_queue_dtmf(channel, 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; } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 96dabba8aa..e92ca267b7 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -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; diff --git a/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c b/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c index 38125acf0c..298ef565e3 100644 --- a/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c +++ b/src/mod/endpoints/mod_wanpipe/mod_wanpipe.c @@ -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; diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c index 7f76b3dfc7..b556303a40 100644 --- a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c +++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c @@ -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; diff --git a/src/mod/languages/mod_spidermonkey_teletone/mod_spidermonkey_teletone.c b/src/mod/languages/mod_spidermonkey_teletone/mod_spidermonkey_teletone.c index 11cb13e1cd..df3dcbb7d8 100644 --- a/src/mod/languages/mod_spidermonkey_teletone/mod_spidermonkey_teletone.c +++ b/src/mod/languages/mod_spidermonkey_teletone/mod_spidermonkey_teletone.c @@ -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)); diff --git a/src/switch_channel.c b/src/switch_channel.c index 41f357df32..5b94afe596 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -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); } diff --git a/src/switch_core.c b/src/switch_core.c index 605d37207e..aeeadac010 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -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); diff --git a/src/switch_core_io.c b/src/switch_core_io.c index a5281f5d17..29a404d024 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -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; diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 1cc88bc773..b57318411a 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -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); diff --git a/src/switch_cpp.cpp b/src/switch_cpp.cpp index 038a0a2701..ae29c36bd9 100644 --- a/src/switch_cpp.cpp +++ b/src/switch_cpp.cpp @@ -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; } diff --git a/src/switch_ivr.c b/src/switch_ivr.c index b2b3c5d6b8..f96fc6e93b 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -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_dtmf_t dtmf = {0}; + int y; + + for (y = 0; y < maxdigits; y++) { + if (switch_channel_dequeue_dtmf(channel, &dtmf) != SWITCH_STATUS_SUCCESS) { + break; + } - switch_channel_dequeue_dtmf(channel, dtmf, maxdigits); - for (i = 0; i < strlen(dtmf); i++) { - - 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; diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index c12b03620e..9a36d65213 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -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; } diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 236b1ee5c7..1a3457d8a3 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -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) { diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index 254b4fe193..51f3b01d9d 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -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; } } diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 5fd76cc45d..2792feb3ba 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -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,61 +1128,29 @@ 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; - if (!switch_rtp_ready(rtp_session)) { - return SWITCH_STATUS_FALSE; - } - - 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)); - } - - 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; -} - - -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) { switch_size_t bytes = 0; - + switch_dtmf_t *_dtmf = NULL; + void *pop; + if (!switch_rtp_ready(rtp_session)) { return bytes; } 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 (switch_queue_trypop(rtp_session->dtmf_data.dtmf_inqueue, &pop) == SWITCH_STATUS_SUCCESS) { + _dtmf = (switch_dtmf_t *) pop; + *dtmf = *_dtmf; + bytes++; } switch_mutex_unlock(rtp_session->dtmf_data.dtmf_mutex); @@ -1188,30 +1158,42 @@ SWITCH_DECLARE(switch_size_t) switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session, } -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) { - 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); + if ((rdigit = malloc(sizeof(*rdigit))) != 0) { + *rdigit = *dtmf; + switch_queue_push(rtp_session->dtmf_data.dtmf_queue, rdigit); + } else { + abort(); + } + + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_DECLARE(switch_status_t) switch_rtp_queue_rfc2833_in(switch_rtp_t *rtp_session, const switch_dtmf_t *dtmf) +{ + + switch_dtmf_t *rdigit; + + if (!switch_rtp_ready(rtp_session)) { + return SWITCH_STATUS_FALSE; } - 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; }