[asterisk-commits] file: branch file/speech-agi r50530 - /team/file/speech-agi/res/res_agi.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Thu Jan 11 12:48:13 MST 2007


Author: file
Date: Thu Jan 11 13:48:12 2007
New Revision: 50530

URL: http://svn.digium.com/view/asterisk?view=rev&rev=50530
Log:
Put in SPEECH RECOGNIZE.

Modified:
    team/file/speech-agi/res/res_agi.c

Modified: team/file/speech-agi/res/res_agi.c
URL: http://svn.digium.com/view/asterisk/team/file/speech-agi/res/res_agi.c?view=diff&rev=50530&r1=50529&r2=50530
==============================================================================
--- team/file/speech-agi/res/res_agi.c (original)
+++ team/file/speech-agi/res/res_agi.c Thu Jan 11 13:48:12 2007
@@ -1429,11 +1429,169 @@
 	return RESULT_SUCCESS;
 }
 
+static int speech_streamfile(struct ast_channel *chan, const char *filename, const char *preflang, int offset)
+{
+	struct ast_filestream *fs = NULL;
+
+	if (!(fs = ast_openstream(chan, filename, preflang)))
+		return -1;
+
+	if (offset)
+		ast_seekstream(fs, offset, SEEK_SET);
+
+	if (ast_applystream(chan, fs))
+		return -1;
+
+	if (ast_playstream(fs))
+		return -1;
+
+	return 0;
+}
+
+
 static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc, char **argv)
 {
-	if (!agi->speech) {
+	struct ast_speech *speech = agi->speech;
+	char *prompt, *mode, dtmf = 0, tmp[4096] = "", *buf = tmp;
+	int timeout = 0, offset = 0, old_read_format = 0, res = 0, i = 0;
+	long current_offset = 0;
+	const char *reason = NULL;
+	struct ast_frame *fr = NULL;
+	struct ast_speech_result *result = NULL;
+	size_t left = sizeof(tmp);
+	time_t start = 0, current;
+
+	if (argc != 5)
+		return RESULT_SHOWUSAGE;
+
+	if (!speech) {
 		fdprintf(agi->fd, "200 result=0\n");
 		return RESULT_SUCCESS;
+	}
+
+	prompt = argv[2];
+	timeout = atoi(argv[3]);
+	mode = argv[4];
+
+	/* If offset is specified then convert from text to integer */
+	if (argc == 6)
+		offset = atoi(argv[5]);
+
+	/* We want frames coming in signed linear */
+	old_read_format = chan->readformat;
+	if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
+		fdprintf(agi->fd, "200 result=0\n");
+		return RESULT_SUCCESS;
+	}
+
+	/* Setup speech structure */
+	if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
+		ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
+		ast_speech_start(speech);
+	}
+
+	/* Start playing prompt */
+	speech_streamfile(chan, prompt, chan->language, offset);
+
+	/* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */
+	while (ast_strlen_zero(reason)) {
+		/* Run scheduled items */
+		ast_sched_runq(chan->sched);
+
+		/* See maximum time of waiting */
+		if ((res = ast_sched_wait(chan->sched)) < 0)
+			res = 1000;
+
+		/* Wait for frame */
+		if (ast_waitfor(chan, res) > 0) {
+			if (!(fr = ast_read(chan))) {
+				reason = "hangup";
+				break;
+			}
+		}
+
+		/* Perform timeout check */
+		if ((timeout > 0) && (start > 0)) {
+			time(&current);
+			if ((current - start) >= timeout) {
+				reason = "timeout";
+				if (fr)
+					ast_frfree(fr);
+				break;
+			}
+		}
+
+		/* Check the speech structure for any changes */
+		ast_mutex_lock(&speech->lock);
+
+		/* See if we need to quiet the audio stream playback */
+		if (ast_test_flag(speech, AST_SPEECH_QUIET) && chan->stream) {
+			current_offset = ast_tellstream(chan->stream);
+			ast_stopstream(chan);
+			ast_clear_flag(speech, AST_SPEECH_QUIET);
+		}
+
+		/* Check each state */
+		switch (speech->state) {
+		case AST_SPEECH_STATE_READY:
+			/* If the stream is done, start timeout calculation */
+			if ((timeout > 0) && ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL))) {
+				ast_stopstream(chan);
+				time(&start);
+			}
+			/* Write audio frame data into speech engine if possible */
+			if (fr && fr->frametype == AST_FRAME_VOICE)
+				ast_speech_write(speech, fr->data, fr->datalen);
+			break;
+		case AST_SPEECH_STATE_WAIT:
+			/* Cue waiting sound if not already playing */
+			if ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL)) {
+				ast_stopstream(chan);
+				/* If a processing sound exists, or is not none - play it */
+				if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none"))
+					speech_streamfile(chan, speech->processing_sound, chan->language, 0);
+			}
+			break;
+		case AST_SPEECH_STATE_DONE:
+			/* Get the results */
+			speech->results = ast_speech_results_get(speech);
+			/* Change state to not ready */
+			ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
+			reason = "speech";
+			break;
+		default:
+			break;
+		}
+		ast_mutex_unlock(&speech->lock);
+
+		/* Check frame for DTMF or hangup */
+		if (fr) {
+			if (fr->frametype == AST_FRAME_DTMF) {
+				reason = "dtmf";
+				dtmf = fr->subclass;
+			} else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass == AST_CONTROL_HANGUP) {
+				reason = "hangup";
+			}
+			ast_frfree(fr);
+		}
+	}
+
+	if (!strcasecmp(reason, "speech")) {
+		/* Build string containing speech results */
+		for (result = speech->results; result; result = result->next) {
+			/* Build result string */
+			ast_build_string(&buf, &left, "%sscore%d=%d text%d=\"%s\" grammar%d=%s", (i > 0 ? " " : ""), i, result->score, i, result->text, i, result->grammar);
+			/* Increment result count */
+			i++;
+		}
+		/* Print out */
+		fdprintf(agi->fd, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp);
+	} else if (!strcasecmp(reason, "dtmf")) {
+		fdprintf(agi->fd, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset);
+	} else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) {
+		fdprintf(agi->fd, "200 result=1 (%s) endpos=%ld\n", reason, current_offset);
+	} else {
+		fdprintf(agi->fd, "200 result=0 endpos=%ld\n", current_offset);
 	}
 
 	return RESULT_SUCCESS;
@@ -1766,7 +1924,8 @@
 "       Deactivates the specified grammar on the speech object.\n";
 
 static char usage_speechrecognize[] =
-" Usage: SPEECH RECOGNIZE\n";
+" Usage: SPEECH RECOGNIZE <prompt> <timeout> <mode> [<offset>]\n"
+"       Plays back given prompt while listening for speech and dtmf.\n";
 
 static agi_command commands[MAX_COMMANDS] = {
 	{ { "answer", NULL }, handle_answer, "Answer channel", usage_answer },



More information about the asterisk-commits mailing list