static void spandsp_dtmf_rx_realtime_callback(void *user_data, int code, int level, int duration)
{
	switch_inband_dtmf_t *pvt = (switch_inband_dtmf_t *)user_data;
	char digit = (char)code;
	pvt->samples += duration;
	if (digit) {
		/* prevent duplicate DTMF */
		if (digit != pvt->last_digit || (pvt->samples - pvt->last_digit_end) > pvt->min_dup_digit_spacing) {
			switch_dtmf_t dtmf = {0};
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "DTMF BEGIN DETECTED: [%c]\n", digit);
			pvt->last_digit = digit;
			dtmf.digit = digit;
			dtmf.duration = switch_core_default_dtmf_duration(0);
			dtmf.source = SWITCH_DTMF_INBAND_AUDIO;
			switch_channel_queue_dtmf(switch_core_session_get_channel(pvt->session), &dtmf);
			pvt->digit_begin = pvt->samples;
		} else {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "DUP DTMF DETECTED: [%c]\n", digit);
			pvt->last_digit_end = pvt->samples;
		}
	} else {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "DTMF END DETECTED: [%c], duration = %u ms\n", pvt->last_digit, (pvt->samples - pvt->digit_begin) / 8);
		pvt->last_digit_end = pvt->samples;
	}
}
Exemple #2
0
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;
	switch_dtmf_t new_dtmf;

	if (switch_channel_down(session->channel)) {
		return SWITCH_STATUS_FALSE;
	}

	switch_assert(dtmf);

	new_dtmf = *dtmf;

	if (new_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), new_dtmf.digit, new_dtmf.duration);
		new_dtmf.duration = switch_core_max_dtmf_duration(0);
	} else if (new_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), new_dtmf.digit, new_dtmf.duration);
		new_dtmf.duration = switch_core_min_dtmf_duration(0);
	} else if (!new_dtmf.duration) {
		new_dtmf.duration = switch_core_default_dtmf_duration(0);
	}


	for (ptr = session->event_hooks.send_dtmf; ptr; ptr = ptr->next) {
		if ((status = ptr->send_dtmf(session, dtmf, SWITCH_DTMF_SEND)) != SWITCH_STATUS_SUCCESS) {
			return SWITCH_STATUS_SUCCESS;
		}
	}

	if (session->endpoint_interface->io_routines->send_dtmf) {
		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, &new_dtmf);
		}
	}
	return status;
}
Exemple #3
0
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;
	switch_dtmf_t new_dtmf;
	int fed = 0;

	if (switch_channel_down(session->channel)) {
		return SWITCH_STATUS_FALSE;
	}

	switch_assert(dtmf);

	new_dtmf = *dtmf;

	if (new_dtmf.duration > switch_core_max_dtmf_duration(0)) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n",
						  switch_channel_get_name(session->channel), new_dtmf.digit, new_dtmf.duration);
		new_dtmf.duration = switch_core_max_dtmf_duration(0);
	} else if (new_dtmf.duration < switch_core_min_dtmf_duration(0)) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n",
						  switch_channel_get_name(session->channel), new_dtmf.digit, new_dtmf.duration);
		new_dtmf.duration = switch_core_min_dtmf_duration(0);
	} else if (!new_dtmf.duration) {
		new_dtmf.duration = switch_core_default_dtmf_duration(0);
	}

	if (!switch_test_flag(dtmf, DTMF_FLAG_SKIP_PROCESS)) {
		if (session->dmachine && !switch_channel_test_flag(session->channel, CF_BROADCAST)) {
			char str[2] = { dtmf->digit, '\0' };
			switch_ivr_dmachine_feed(session->dmachine, str, NULL);
			fed = 1;
		}

		for (ptr = session->event_hooks.recv_dtmf; ptr; ptr = ptr->next) {
			if ((status = ptr->recv_dtmf(session, &new_dtmf, SWITCH_DTMF_RECV)) != SWITCH_STATUS_SUCCESS) {
				return status;
			}
		}
	}

	return fed ? SWITCH_STATUS_FALSE : SWITCH_STATUS_SUCCESS;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}