#include "precompile.h" #include "audiodtmf.h" #include "audiocontext.h" #include "audiolog.h" #include "audiostream.h" #define TX_DTMF_INTERVAL 320 static void process_frame(void *self) { audiodtmf_t *dtmf = CONTAINING_RECORD(self, audiodtmf_t, base); apr_status_t status; if (!dtmf->binitialized) return; if (dtmf->fin) return; dtmf->progress += FRAME_TIME; if (dtmf->bsender) { /* act as sender */ if (dtmf->progress >= TX_DTMF_INTERVAL) { if (dtmf->tx_digits_offset < dtmf->tx_digits_len) { /* send one digit */ status = audiortp_send_dtmf(dtmf->rtp, dtmf->tx_digits + dtmf->tx_digits_offset, 1); if (status == APR_SUCCESS) { dtmf->tx_digits_offset ++; if (dtmf->tx_digits_offset == dtmf->tx_digits_len) { audiodriver_raise_event(&dtmf->base, DRIVER_EVT_DTMF_SENT, 0, 0); dtmf->fin = 1; } } else { AUDIO_LOG_ERROR("send dtmf to rtp stream failed!"); audiodriver_raise_event(&dtmf->base, DRIVER_EVT_DTMF_SENT, status, 0); dtmf->fin = 1; } } dtmf->progress -= TX_DTMF_INTERVAL; } } else { /* act as receiver */ char tmp[MAX_DTMF]; unsigned int tmp_cnt = MAX_DTMF; if (dtmf->rx_timeout != -1) { dtmf->rx_ellapsed += FRAME_TIME; if (dtmf->rx_ellapsed >= dtmf->rx_timeout) { audiodriver_raise_event(&dtmf->base, DRIVER_EVT_DTMF_RECV, -1, (int)&dtmf->rx_digits[0]); dtmf->fin = 1; return; } } status = audiortp_recv_dtmf(dtmf->rtp, &tmp[0], &tmp_cnt); if (status == APR_SUCCESS) { unsigned int i; for (i = 0; i < tmp_cnt; ++i) { char ch = tmp[i]; if (ch == dtmf->rx_interdigit) { dtmf->rx_digits[dtmf->rx_digits_len] = 0; audiodriver_raise_event(&dtmf->base, DRIVER_EVT_DTMF_RECV, 0, (int)&dtmf->rx_digits[0]); dtmf->fin = 1; } else { dtmf->rx_digits[dtmf->rx_digits_len++] = ch; if (dtmf->rx_digits_len == dtmf->rx_maxdigits) { audiodriver_raise_event(&dtmf->base, DRIVER_EVT_DTMF_RECV, 0, (int)&dtmf->rx_digits[0]); dtmf->fin = 1; } } } } else { AUDIO_LOG_ERROR("recv dtmf from rtp stream failed!"); audiodriver_raise_event(&dtmf->base, DRIVER_EVT_DTMF_RECV, status, 0); dtmf->fin = 1; } } } static audiodriver_vtbl_t g_driver_vtbl = { &process_frame, }; apr_status_t audiodtmf_create(apr_pool_t *pool, audioengine_t *engine, audiodtmf_t **p_dtmf) { audiodtmf_t *dtmf; dtmf = apr_palloc(pool, sizeof(audiodtmf_t)); memset(dtmf, 0, sizeof(audiodtmf_t)); dtmf->rtp = NULL; dtmf->bsender = 0; dtmf->tx_digits = NULL; dtmf->tx_digits_len = 0; dtmf->tx_digits_offset = 0; dtmf->rx_maxdigits = MAX_DTMF; dtmf->rx_interval = 100; // 100ms dtmf->rx_timeout = -1; dtmf->rx_interdigit = 0; dtmf->binitialized = FALSE; dtmf->progress = 0; audiodriver_init(engine, &g_driver_vtbl, &dtmf->base); *p_dtmf = dtmf; return APR_SUCCESS; } void audiodtmf_destroy(audiodtmf_t *dtmf) { if (dtmf->tx_digits) free(dtmf->tx_digits); } apr_status_t audiodtmf_set_rtpstream(audiodtmf_t *dtmf, audiortp_t* rtp) { dtmf->rtp = rtp; return APR_SUCCESS; } apr_status_t audiodtmf_set_sender(audiodtmf_t *dtmf, int on) { dtmf->bsender = !!on; return APR_SUCCESS; } apr_status_t audiodtmf_set_txparam(audiodtmf_t *dtmf, const char *digits, int n) { if (n == -1) n = strlen(digits); dtmf->tx_digits_len = n; dtmf->tx_digits_offset = 0; dtmf->tx_digits = realloc(dtmf->tx_digits, n + 1); strncpy(dtmf->tx_digits, digits, n); return APR_SUCCESS; } apr_status_t audiodtmf_set_rxparam(audiodtmf_t *dtmf, int maxdigit, int interval, int interdigit, int timeout) { dtmf->rx_interdigit = interdigit; dtmf->rx_interval = interval; dtmf->rx_maxdigits = maxdigit; dtmf->rx_timeout = timeout; return APR_SUCCESS; } apr_status_t audiodtmf_init(audiodtmf_t *dtmf) { if (dtmf->binitialized) return APR_EAGAIN; if (!dtmf->rtp) return APR_EGENERAL; if (dtmf->bsender) { if (!dtmf->tx_digits) return APR_EGENERAL; } dtmf->binitialized = TRUE; dtmf->progress = 0; dtmf->rx_digits_len = 0; dtmf->rx_ellapsed = 0; dtmf->fin = 0; return APR_SUCCESS; } apr_status_t audiodtmf_term(audiodtmf_t *dtmf) { if (dtmf->binitialized) { dtmf->binitialized = FALSE; return APR_SUCCESS; } return APR_EGENERAL; }