예제 #1
0
static int i4l_startrec(struct ast_modem_pvt *p)
{
    if (ast_modem_send(p, "AT+VRX+VTX", 0) ||
            ast_modem_expect(p, "CONNECT", 5)) {
        ast_log(LOG_WARNING, "Unable to start recording\n");
        return -1;
    }
    p->ministate = STATE_VOICE;

    /*  let ast dsp detect dtmf */
    if (p->dtmfmode & MODEM_DTMF_AST) {
        if (p->dsp) {
            ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", p->dev);
        } else {
            p->dsp = ast_dsp_new();
            if (p->dsp) {
                ast_log(LOG_DEBUG, "Detecting DTMF inband with sw DSP on %s\n",p->dev);
                ast_dsp_set_features(p->dsp, DSP_FEATURE_DTMF_DETECT|DSP_FEATURE_FAX_DETECT);
                ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | 0);
            }
        }
    }

    return 0;
}
예제 #2
0
static int i4l_answer(struct ast_modem_pvt *p)
{
    if (ast_modem_send(p, "ATA\r", 4) ||
            ast_modem_expect(p, "VCON", 10)) {
        ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
        return -1;
    }
#if 1
    if (ast_modem_send(p, "AT+VDD=0,8", 0) ||
            ast_modem_expect(p, "OK", 5)) {
        ast_log(LOG_WARNING, "Unable to set to phone line interface\n");
        return -1;
    }
#endif
    if (ast_modem_send(p, "AT+VTX+VRX", 0) ||
            ast_modem_expect(p, "CONNECT", 10)) {
        ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
        return -1;
    }
    p->ministate = STATE_VOICE;

    /*  let ast dsp detect dtmf */
    if (p->dtmfmode & MODEM_DTMF_AST) {
        if (p->dsp) {
            ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", p->dev);
        } else {
            p->dsp = ast_dsp_new();
            if (p->dsp) {
                ast_log(LOG_DEBUG, "Detecting DTMF inband with sw DSP on %s\n",p->dev);
                ast_dsp_set_features(p->dsp, DSP_FEATURE_DTMF_DETECT|DSP_FEATURE_FAX_DETECT);
                ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | 0);
            }
        }
    }

    return 0;
}
예제 #3
0
static int nv_detectfax_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct ast_module_user *u;
	char tmp[256] = "\0";
	char *p = NULL;
	char *waitstr = NULL;
	char *options = NULL;
	char *silstr = NULL;
	char *minstr = NULL;
	char *maxstr = NULL;
	struct ast_frame *fr = NULL;
	struct ast_frame *fr2 = NULL;
	int notsilent = 0;
	struct timeval start = {0, 0}, end = {0, 0};
	int waitdur = 4;
	int sildur = 1000;
	int mindur = 100;
	int maxdur = -1;
	int skipanswer = 0;
	int noextneeded = 0;
	int ignoredtmf = 0;
	int ignorefax = 0;
	int ignoretalk = 0;
	int x = 0;
	int origrformat = 0;
	int features = 0;
	time_t timeout = 0;
	struct ast_dsp *dsp = NULL;

	pbx_builtin_setvar_helper(chan, "FAX_DETECTED", "");
	pbx_builtin_setvar_helper(chan, "FAXEXTEN", "");
	pbx_builtin_setvar_helper(chan, "DTMF_DETECTED", "");
	pbx_builtin_setvar_helper(chan, "TALK_DETECTED", "");

	if (data || !ast_strlen_zero((char *)data)) {
		strncpy(tmp, (char *)data, sizeof(tmp)-1);
	}

	p = tmp;

	waitstr = strsep(&p, "|");
	options = strsep(&p, "|");
	silstr = strsep(&p, "|");
	minstr = strsep(&p, "|");
	maxstr = strsep(&p, "|");

	if (waitstr) {
		if ((sscanf(waitstr, "%d", &x) == 1) && (x > 0))
			waitdur = x;
	}

	if (options) {
		if (strchr(options, 'n'))
			skipanswer = 1;
		if (strchr(options, 'x'))
			noextneeded = 1;
		if (strchr(options, 'd'))
			ignoredtmf = 1;
		if (strchr(options, 'f'))
			ignorefax = 1;
		if (strchr(options, 't'))
			ignoretalk = 1;
	}

	if (silstr) {
		if ((sscanf(silstr, "%d", &x) == 1) && (x > 0))
			sildur = x;
	}

	if (minstr) {
		if ((sscanf(minstr, "%d", &x) == 1) && (x > 0))
			mindur = x;
	}

	if (maxstr) {
		if ((sscanf(maxstr, "%d", &x) == 1) && (x > 0))
			maxdur = x;
	}

	ast_log(LOG_DEBUG, "Preparing detect of fax (waitdur=%ds, sildur=%dms, mindur=%dms, maxdur=%dms)\n",
						waitdur, sildur, mindur, maxdur);

	u = ast_module_user_add(chan);

	if (chan->_state != AST_STATE_UP && !skipanswer) {
		/* Otherwise answer unless we're supposed to send this while on-hook */
		res = ast_answer(chan);
	}
	if (!res) {
		origrformat = chan->readformat;
		if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)))
			ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
	}
	if (!(dsp = ast_dsp_new())) {
		ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
		res = -1;
	}

	if (dsp) {
#if 0
		if (!ignoretalk)
			; /* features |= DSP_FEATURE_SILENCE_SUPPRESS; */
#endif
		if (!ignorefax)
			features |= DSP_FEATURE_FAX_DETECT;
		if (!ignoredtmf)
			features |= DSP_FEATURE_DTMF_DETECT;

		ast_dsp_set_threshold(dsp, 256);
		ast_dsp_set_features(dsp, features | DSP_DIGITMODE_RELAXDTMF);
		ast_dsp_digitmode(dsp, DSP_DIGITMODE_DTMF);
	}

	if (!res) {
		if (waitdur > 0)
			timeout = time(NULL) + (time_t)waitdur;

		while (ast_waitfor(chan, 50) > -1) {
			if (waitdur > 0 && time(NULL) > timeout) {
				res = 0;
				break;
			}

			fr = ast_read(chan);
			if (!fr) {
				ast_log(LOG_DEBUG, "Got hangup\n");
				res = -1;
				break;
			}

			/* Duplicate frame because ast_dsp_process may free the frame passed */
			fr2 = ast_frdup(fr);

			/* Do not pass channel to ast_dsp_process otherwise it may queue modified audio frame back */
			fr2 = ast_dsp_process(NULL, dsp, fr2);
			if (!fr2) {
				ast_log(LOG_ERROR, "Bad DSP received (what happened?)\n");
				ast_frfree(fr);
				res = 0;
				break;
			}

			if (fr2->frametype == AST_FRAME_DTMF) {
				if (fr2->subclass == 'f' && !ignorefax) {
					/* Fax tone -- Handle and return NULL */
					ast_log(LOG_DEBUG, "Fax detected on %s\n", chan->name);
					if (strcmp(chan->exten, "fax")) {
						ast_log(LOG_NOTICE, "Redirecting '%s' to fax extension on context '%s'\n", chan->name, chan->context);
						pbx_builtin_setvar_helper(chan, "FAX_DETECTED", "1");
						pbx_builtin_setvar_helper(chan, "FAXEXTEN", chan->exten);

						if (ast_exists_extension(chan, chan->context, "fax", 1, chan->CALLERID_FIELD)) {
							/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
							strncpy(chan->exten, "fax", sizeof(chan->exten)-1);
							chan->priority = 0;
						} else
							ast_log(LOG_WARNING, "Fax detected, but no fax extension\n");
					} else
						ast_log(LOG_WARNING, "Already in a fax extension, not redirecting\n");

					res = 0;
					ast_frfree(fr);
					ast_frfree(fr2);
					break;
				} else if (!ignoredtmf) {
					ast_log(LOG_DEBUG, "DTMF detected on %s\n", chan->name);
					char t[2];
					t[0] = fr2->subclass;
					t[1] = '\0';
					if (noextneeded || ast_canmatch_extension(chan, chan->context, t, 1, chan->CALLERID_FIELD)) {
						pbx_builtin_setvar_helper(chan, "DTMF_DETECTED", "1");
						/* They entered a valid extension, or might be anyhow */
						if (noextneeded) {
							ast_log(LOG_NOTICE, "DTMF received (not matching to exten)\n");
							res = 0;
						} else {
							ast_log(LOG_NOTICE, "DTMF received (matching to exten)\n");
							res = fr2->subclass;
						}
						ast_frfree(fr);
						ast_frfree(fr2);
						break;
					} else
						ast_log(LOG_DEBUG, "Valid extension requested and DTMF did not match\n");
				}
			} else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR) && !ignoretalk) {
				int totalsilence;
				int ms;
				res = ast_dsp_silence(dsp, fr, &totalsilence);
				if (res && (totalsilence > sildur)) {
					/* We've been quiet a little while */
					if (notsilent) {
						/* We had heard some talking */
						gettimeofday(&end, NULL);
						ms = (end.tv_sec - start.tv_sec) * 1000;
						ms += (end.tv_usec - start.tv_usec) / 1000;
						ms -= sildur;
						if (ms < 0)
							ms = 0;
						if ((ms > mindur) && ((maxdur < 0) || (ms < maxdur))) {
							char ms_str[10];
							ast_log(LOG_DEBUG, "Found qualified token of %d ms\n", ms);
							ast_log(LOG_NOTICE, "Redirecting %s to talk extension\n", chan->name);

							/* Save detected talk time (in milliseconds) */
							sprintf(ms_str, "%d", ms);
							pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);

							if (ast_exists_extension(chan, chan->context, "talk", 1, chan->CALLERID_FIELD)) {
								strncpy(chan->exten, "talk", sizeof(chan->exten) - 1);
								chan->priority = 0;
							} else
								ast_log(LOG_WARNING, "Talk detected, but no talk extension\n");
							res = 0;
							ast_frfree(fr);
							ast_frfree(fr2);
							break;
						} else
							ast_log(LOG_DEBUG, "Found unqualified token of %d ms\n", ms);
						notsilent = 0;
					}
				} else {
					if (!notsilent) {
						/* Heard some audio, mark the begining of the token */
						gettimeofday(&start, NULL);
						ast_log(LOG_DEBUG, "Start of voice token!\n");
						notsilent = 1;
					}
				}
			}
			ast_frfree(fr);
			ast_frfree(fr2);
		}
	} else
		ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);

	if (res > -1) {
		if (origrformat && ast_set_read_format(chan, origrformat)) {
			ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n",
				chan->name, ast_getformatname(origrformat));
		}
	}

	if (dsp)
		ast_dsp_free(dsp);

	ast_module_user_remove(u);

	return res;
}