SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf_string(switch_core_session_t *session, const char *dtmf_string) { char *p; switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0) }; int sent = 0, dur; char *string; int i, argc; char *argv[256]; int dur_total = 0; switch_assert(session != NULL); if (switch_channel_down(session->channel)) { return SWITCH_STATUS_FALSE; } if (zstr(dtmf_string)) { return SWITCH_STATUS_FALSE; } if (strlen(dtmf_string) > 99) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Attempt to send very large dtmf string ignored!\n"); return SWITCH_STATUS_FALSE; } string = switch_core_session_strdup(session, dtmf_string); argc = switch_separate_string(string, '+', argv, (sizeof(argv) / sizeof(argv[0]))); if (argc) { switch_channel_pre_answer(session->channel); } for (i = 0; i < argc; i++) { dtmf.duration = switch_core_default_dtmf_duration(0); dur = switch_core_default_dtmf_duration(0) / 8; if ((p = strchr(argv[i], '@'))) { *p++ = '\0'; if ((dur = atoi(p)) > 50) { dtmf.duration = dur * 8; } } if (dtmf.duration > switch_core_max_dtmf_duration(0)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n", switch_channel_get_name(session->channel), dtmf.digit, dtmf.duration); dtmf.duration = switch_core_max_dtmf_duration(0); } else if (dtmf.duration < switch_core_min_dtmf_duration(0)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n", switch_channel_get_name(session->channel), dtmf.digit, dtmf.duration); dtmf.duration = switch_core_min_dtmf_duration(0); } else if (!dtmf.duration) { dtmf.duration = switch_core_default_dtmf_duration(0); } for (p = argv[i]; p && *p; p++) { if (is_dtmf(*p)) { dtmf.digit = *p; if (switch_core_session_send_dtmf(session, &dtmf) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s send dtmf\ndigit=%c ms=%u samples=%u\n", switch_channel_get_name(session->channel), dtmf.digit, dur, dtmf.duration); sent++; dur_total += dtmf.duration + 2000; /* account for 250ms pause */ } } } if (dur_total) { char tmp[32] = ""; switch_snprintf(tmp, sizeof(tmp), "%d", dur_total / 8); switch_channel_set_variable(session->channel, "last_dtmf_duration", tmp); } } return sent ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; }
static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) { ftdm_wait_flag_t wflags = FTDM_READ; ftdm_status_t status; ctdm_private_t *tech_pvt; const char *name; switch_channel_t *channel; int chunk; uint32_t span_id, chan_id; ftdm_size_t len; char dtmf[128] = ""; channel = switch_core_session_get_channel(session); assert(channel != NULL); tech_pvt = switch_core_session_get_private(session); assert(tech_pvt != NULL); name = switch_channel_get_name(channel); top: wflags = FTDM_READ; chunk = ftdm_channel_get_io_interval(tech_pvt->ftdm_channel) * 2; status = ftdm_channel_wait(tech_pvt->ftdm_channel, &wflags, chunk); span_id = ftdm_channel_get_span_id(tech_pvt->ftdm_channel); chan_id = ftdm_channel_get_id(tech_pvt->ftdm_channel); if (status == FTDM_FAIL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id); goto fail; } if (status == FTDM_TIMEOUT) { goto top; } if (!(wflags & FTDM_READ)) { goto top; } len = tech_pvt->read_frame.buflen; if (ftdm_channel_read(tech_pvt->ftdm_channel, tech_pvt->read_frame.data, &len) != FTDM_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id); } *frame = &tech_pvt->read_frame; tech_pvt->read_frame.datalen = (uint32_t)len; tech_pvt->read_frame.samples = tech_pvt->read_frame.datalen; tech_pvt->read_frame.codec = &tech_pvt->read_codec; if (ftdm_channel_get_codec(tech_pvt->ftdm_channel) == FTDM_CODEC_SLIN) { tech_pvt->read_frame.samples /= 2; } while (ftdm_channel_dequeue_dtmf(tech_pvt->ftdm_channel, dtmf, sizeof(dtmf))) { switch_dtmf_t _dtmf = { 0, switch_core_default_dtmf_duration(0) }; char *p; for (p = dtmf; p && *p; p++) { if (is_dtmf(*p)) { _dtmf.digit = *p; ftdm_log(FTDM_LOG_DEBUG, "Queuing DTMF [%c] in channel %s device %d:%d\n", *p, name, span_id, chan_id); switch_channel_queue_dtmf(channel, &_dtmf); } } } return SWITCH_STATUS_SUCCESS; fail: return SWITCH_STATUS_GENERR; }