[svn-commits] file: branch file/speech-agi r50530 -
/team/file/speech-agi/res/res_agi.c
svn-commits at lists.digium.com
svn-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(¤t);
+ 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 svn-commits
mailing list