dtmf overhaul testers wanted
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6952 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
601f7b6e4a
commit
2931fc9109
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
///\}
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
124
src/switch_rtp.c
124
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue