00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "asterisk.h"
00029
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 179256 $");
00031
00032 #include "asterisk/file.h"
00033 #include "asterisk/channel.h"
00034 #include "asterisk/pbx.h"
00035 #include "asterisk/module.h"
00036 #include "asterisk/lock.h"
00037 #include "asterisk/app.h"
00038 #include "asterisk/speech.h"
00039
00040
00041 static char *speechcreate_descrip =
00042 " SpeechCreate(engine name):\n"
00043 "This application creates information to be used by all the other applications.\n"
00044 "It must be called before doing any speech recognition activities such as activating a grammar.\n"
00045 "It takes the engine name to use as the argument, if not specified the default engine will be used.\n";
00046
00047 static char *speechactivategrammar_descrip =
00048 " SpeechActivateGrammar(Grammar Name):\n"
00049 "This activates the specified grammar to be recognized by the engine.\n"
00050 "A grammar tells the speech recognition engine what to recognize, and how to portray it back to you \n"
00051 "in the dialplan. The grammar name is the only argument to this application.\n";
00052
00053 static char *speechstart_descrip =
00054 " SpeechStart():\n"
00055 "Tell the speech recognition engine that it should start trying to get results from audio being \n"
00056 "fed to it. This has no arguments.\n";
00057
00058 static char *speechbackground_descrip =
00059 " SpeechBackground(<Sound File>[,Timeout[,options]]):\n"
00060 "This application plays a sound file and waits for the person to speak. Once they start speaking playback\n"
00061 "of the file stops, and silence is heard. Once they stop talking the processing sound is played to indicate\n"
00062 "the speech recognition engine is working. Once results are available the application returns and results \n"
00063 "(score and text) are available using dialplan functions.\n"
00064 " The first text and score are ${SPEECH_TEXT(0)} AND ${SPEECH_SCORE(0)} while the second are ${SPEECH_TEXT(1)}\n"
00065 "and ${SPEECH_SCORE(1)}.\n"
00066 " The first argument is the sound file and the second is the timeout integer in seconds. Note the timeout will\n"
00067 "only start once the sound file has stopped playing. The third argument specifies options:\n"
00068 " Valid Options:\n"
00069 " n - Don't answer the channel if it has not already been answered.\n";
00070
00071 static char *speechdeactivategrammar_descrip =
00072 " SpeechDeactivateGrammar(Grammar Name):\n"
00073 "This deactivates the specified grammar so that it is no longer recognized.\n"
00074 "The only argument is the grammar name to deactivate.\n";
00075
00076 static char *speechprocessingsound_descrip =
00077 " SpeechProcessingSound(Sound File):\n"
00078 "This changes the processing sound that SpeechBackground plays back when the speech recognition engine is\n"
00079 "processing and working to get results.\n"
00080 "It takes the sound file as the only argument.\n";
00081
00082 static char *speechdestroy_descrip =
00083 " SpeechDestroy():\n"
00084 "This destroys the information used by all the other speech recognition applications.\n"
00085 "If you call this application but end up wanting to recognize more speech, you must call SpeechCreate\n"
00086 "again before calling any other application. It takes no arguments.\n";
00087
00088 static char *speechload_descrip =
00089 " SpeechLoadGrammar(Grammar Name,Path):\n"
00090 "Load a grammar only on the channel, not globally.\n"
00091 "It takes the grammar name as first argument and path as second.\n";
00092
00093 static char *speechunload_descrip =
00094 " SpeechUnloadGrammar(Grammar Name):\n"
00095 "Unload a grammar. It takes the grammar name as the only argument.\n";
00096
00097
00098 static void destroy_callback(void *data)
00099 {
00100 struct ast_speech *speech = (struct ast_speech*)data;
00101
00102 if (speech == NULL) {
00103 return;
00104 }
00105
00106
00107 ast_speech_destroy(speech);
00108
00109 return;
00110 }
00111
00112
00113 static const struct ast_datastore_info speech_datastore = {
00114 .type = "speech",
00115 .destroy = destroy_callback
00116 };
00117
00118
00119 static struct ast_speech *find_speech(struct ast_channel *chan)
00120 {
00121 struct ast_speech *speech = NULL;
00122 struct ast_datastore *datastore = NULL;
00123
00124 datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL);
00125 if (datastore == NULL) {
00126 return NULL;
00127 }
00128 speech = datastore->data;
00129
00130 return speech;
00131 }
00132
00133
00134 static struct ast_speech_result *find_result(struct ast_speech_result *results, char *result_num)
00135 {
00136 struct ast_speech_result *result = results;
00137 char *tmp = NULL;
00138 int nbest_num = 0, wanted_num = 0, i = 0;
00139
00140 if (!result) {
00141 return NULL;
00142 }
00143
00144 if ((tmp = strchr(result_num, '/'))) {
00145 *tmp++ = '\0';
00146 nbest_num = atoi(result_num);
00147 wanted_num = atoi(tmp);
00148 } else {
00149 wanted_num = atoi(result_num);
00150 }
00151
00152 do {
00153 if (result->nbest_num != nbest_num)
00154 continue;
00155 if (i == wanted_num)
00156 break;
00157 i++;
00158 } while ((result = AST_LIST_NEXT(result, list)));
00159
00160 return result;
00161 }
00162
00163
00164 static int speech_score(struct ast_channel *chan, const char *cmd, char *data,
00165 char *buf, size_t len)
00166 {
00167 struct ast_speech_result *result = NULL;
00168 struct ast_speech *speech = find_speech(chan);
00169 char tmp[128] = "";
00170
00171 if (data == NULL || speech == NULL || !(result = find_result(speech->results, data))) {
00172 return -1;
00173 }
00174
00175 snprintf(tmp, sizeof(tmp), "%d", result->score);
00176
00177 ast_copy_string(buf, tmp, len);
00178
00179 return 0;
00180 }
00181
00182 static struct ast_custom_function speech_score_function = {
00183 .name = "SPEECH_SCORE",
00184 .synopsis = "Gets the confidence score of a result.",
00185 .syntax = "SPEECH_SCORE([nbest number/]result number)",
00186 .desc =
00187 "Gets the confidence score of a result.\n",
00188 .read = speech_score,
00189 .write = NULL,
00190 };
00191
00192
00193 static int speech_text(struct ast_channel *chan, const char *cmd, char *data,
00194 char *buf, size_t len)
00195 {
00196 struct ast_speech_result *result = NULL;
00197 struct ast_speech *speech = find_speech(chan);
00198
00199 if (data == NULL || speech == NULL || !(result = find_result(speech->results, data))) {
00200 return -1;
00201 }
00202
00203 if (result->text != NULL) {
00204 ast_copy_string(buf, result->text, len);
00205 } else {
00206 buf[0] = '\0';
00207 }
00208
00209 return 0;
00210 }
00211
00212 static struct ast_custom_function speech_text_function = {
00213 .name = "SPEECH_TEXT",
00214 .synopsis = "Gets the recognized text of a result.",
00215 .syntax = "SPEECH_TEXT([nbest number/]result number)",
00216 .desc =
00217 "Gets the recognized text of a result.\n",
00218 .read = speech_text,
00219 .write = NULL,
00220 };
00221
00222
00223 static int speech_grammar(struct ast_channel *chan, const char *cmd, char *data,
00224 char *buf, size_t len)
00225 {
00226 struct ast_speech_result *result = NULL;
00227 struct ast_speech *speech = find_speech(chan);
00228
00229 if (data == NULL || speech == NULL || !(result = find_result(speech->results, data))) {
00230 return -1;
00231 }
00232
00233 if (result->grammar != NULL) {
00234 ast_copy_string(buf, result->grammar, len);
00235 } else {
00236 buf[0] = '\0';
00237 }
00238
00239 return 0;
00240 }
00241
00242 static struct ast_custom_function speech_grammar_function = {
00243 .name = "SPEECH_GRAMMAR",
00244 .synopsis = "Gets the matched grammar of a result if available.",
00245 .syntax = "SPEECH_GRAMMAR([nbest number/]result number)",
00246 .desc =
00247 "Gets the matched grammar of a result if available.\n",
00248 .read = speech_grammar,
00249 .write = NULL,
00250 };
00251
00252
00253 static int speech_engine_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00254 {
00255 struct ast_speech *speech = find_speech(chan);
00256
00257 if (data == NULL || speech == NULL) {
00258 return -1;
00259 }
00260
00261 ast_speech_change(speech, data, value);
00262
00263 return 0;
00264 }
00265
00266 static struct ast_custom_function speech_engine_function = {
00267 .name = "SPEECH_ENGINE",
00268 .synopsis = "Change a speech engine specific attribute.",
00269 .syntax = "SPEECH_ENGINE(name)=value",
00270 .desc =
00271 "Changes a speech engine specific attribute.\n",
00272 .read = NULL,
00273 .write = speech_engine_write,
00274 };
00275
00276
00277 static int speech_results_type_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00278 {
00279 struct ast_speech *speech = find_speech(chan);
00280
00281 if (data == NULL || speech == NULL)
00282 return -1;
00283
00284 if (!strcasecmp(value, "normal"))
00285 ast_speech_change_results_type(speech, AST_SPEECH_RESULTS_TYPE_NORMAL);
00286 else if (!strcasecmp(value, "nbest"))
00287 ast_speech_change_results_type(speech, AST_SPEECH_RESULTS_TYPE_NBEST);
00288
00289 return 0;
00290 }
00291
00292 static struct ast_custom_function speech_results_type_function = {
00293 .name = "SPEECH_RESULTS_TYPE",
00294 .synopsis = "Sets the type of results that will be returned.",
00295 .syntax = "SPEECH_RESULTS_TYPE()=results type",
00296 .desc =
00297 "Sets the type of results that will be returned. Valid options are normal or nbest.",
00298 .read = NULL,
00299 .write = speech_results_type_write,
00300 };
00301
00302
00303 static int speech_read(struct ast_channel *chan, const char *cmd, char *data,
00304 char *buf, size_t len)
00305 {
00306 int results = 0;
00307 struct ast_speech_result *result = NULL;
00308 struct ast_speech *speech = find_speech(chan);
00309 char tmp[128] = "";
00310
00311
00312 if (!strcasecmp(data, "status")) {
00313 if (speech != NULL)
00314 ast_copy_string(buf, "1", len);
00315 else
00316 ast_copy_string(buf, "0", len);
00317 return 0;
00318 }
00319
00320
00321 if (speech == NULL) {
00322 return -1;
00323 }
00324
00325
00326 if (!strcasecmp(data, "spoke")) {
00327 if (ast_test_flag(speech, AST_SPEECH_SPOKE))
00328 ast_copy_string(buf, "1", len);
00329 else
00330 ast_copy_string(buf, "0", len);
00331 } else if (!strcasecmp(data, "results")) {
00332
00333 for (result = speech->results; result; result = AST_LIST_NEXT(result, list))
00334 results++;
00335 snprintf(tmp, sizeof(tmp), "%d", results);
00336 ast_copy_string(buf, tmp, len);
00337 } else {
00338 buf[0] = '\0';
00339 }
00340
00341 return 0;
00342 }
00343
00344 static struct ast_custom_function speech_function = {
00345 .name = "SPEECH",
00346 .synopsis = "Gets information about speech recognition results.",
00347 .syntax = "SPEECH(argument)",
00348 .desc =
00349 "Gets information about speech recognition results.\n"
00350 "status: Returns 1 upon speech object existing, or 0 if not\n"
00351 "spoke: Returns 1 if spoker spoke, or 0 if not\n"
00352 "results: Returns number of results that were recognized\n",
00353 .read = speech_read,
00354 .write = NULL,
00355 };
00356
00357
00358
00359
00360 static int speech_create(struct ast_channel *chan, void *data)
00361 {
00362 struct ast_speech *speech = NULL;
00363 struct ast_datastore *datastore = NULL;
00364
00365
00366 speech = ast_speech_new(data, chan->nativeformats);
00367 if (speech == NULL) {
00368
00369 pbx_builtin_setvar_helper(chan, "ERROR", "1");
00370 return 0;
00371 }
00372
00373 datastore = ast_datastore_alloc(&speech_datastore, NULL);
00374 if (datastore == NULL) {
00375 ast_speech_destroy(speech);
00376 pbx_builtin_setvar_helper(chan, "ERROR", "1");
00377 return 0;
00378 }
00379 pbx_builtin_setvar_helper(chan, "ERROR", NULL);
00380 datastore->data = speech;
00381 ast_channel_datastore_add(chan, datastore);
00382
00383 return 0;
00384 }
00385
00386
00387 static int speech_load(struct ast_channel *chan, void *vdata)
00388 {
00389 int res = 0;
00390 struct ast_speech *speech = find_speech(chan);
00391 char *data;
00392 AST_DECLARE_APP_ARGS(args,
00393 AST_APP_ARG(grammar);
00394 AST_APP_ARG(path);
00395 );
00396
00397 data = ast_strdupa(vdata);
00398 AST_STANDARD_APP_ARGS(args, data);
00399
00400 if (speech == NULL)
00401 return -1;
00402
00403 if (args.argc != 2)
00404 return -1;
00405
00406
00407 res = ast_speech_grammar_load(speech, args.grammar, args.path);
00408
00409 return res;
00410 }
00411
00412
00413 static int speech_unload(struct ast_channel *chan, void *data)
00414 {
00415 int res = 0;
00416 struct ast_speech *speech = find_speech(chan);
00417
00418 if (speech == NULL)
00419 return -1;
00420
00421
00422 res = ast_speech_grammar_unload(speech, data);
00423
00424 return res;
00425 }
00426
00427
00428 static int speech_deactivate(struct ast_channel *chan, void *data)
00429 {
00430 int res = 0;
00431 struct ast_speech *speech = find_speech(chan);
00432
00433 if (speech == NULL)
00434 return -1;
00435
00436
00437 res = ast_speech_grammar_deactivate(speech, data);
00438
00439 return res;
00440 }
00441
00442
00443 static int speech_activate(struct ast_channel *chan, void *data)
00444 {
00445 int res = 0;
00446 struct ast_speech *speech = find_speech(chan);
00447
00448 if (speech == NULL)
00449 return -1;
00450
00451
00452 res = ast_speech_grammar_activate(speech, data);
00453
00454 return res;
00455 }
00456
00457
00458 static int speech_start(struct ast_channel *chan, void *data)
00459 {
00460 int res = 0;
00461 struct ast_speech *speech = find_speech(chan);
00462
00463 if (speech == NULL)
00464 return -1;
00465
00466 ast_speech_start(speech);
00467
00468 return res;
00469 }
00470
00471
00472 static int speech_processing_sound(struct ast_channel *chan, void *data)
00473 {
00474 int res = 0;
00475 struct ast_speech *speech = find_speech(chan);
00476
00477 if (speech == NULL)
00478 return -1;
00479
00480 if (speech->processing_sound != NULL) {
00481 ast_free(speech->processing_sound);
00482 speech->processing_sound = NULL;
00483 }
00484
00485 speech->processing_sound = ast_strdup(data);
00486
00487 return res;
00488 }
00489
00490
00491 static int speech_streamfile(struct ast_channel *chan, const char *filename, const char *preflang)
00492 {
00493 struct ast_filestream *fs = NULL;
00494
00495 if (!(fs = ast_openstream(chan, filename, preflang)))
00496 return -1;
00497
00498 if (ast_applystream(chan, fs))
00499 return -1;
00500
00501 ast_playstream(fs);
00502
00503 return 0;
00504 }
00505
00506 enum {
00507 SB_OPT_NOANSWER = (1 << 0),
00508 };
00509
00510 AST_APP_OPTIONS(speech_background_options, BEGIN_OPTIONS
00511 AST_APP_OPTION('n', SB_OPT_NOANSWER),
00512 END_OPTIONS );
00513
00514
00515 static int speech_background(struct ast_channel *chan, void *data)
00516 {
00517 unsigned int timeout = 0;
00518 int res = 0, done = 0, started = 0, quieted = 0, max_dtmf_len = 0;
00519 struct ast_speech *speech = find_speech(chan);
00520 struct ast_frame *f = NULL;
00521 int oldreadformat = AST_FORMAT_SLINEAR;
00522 char dtmf[AST_MAX_EXTENSION] = "";
00523 struct timeval start = { 0, 0 }, current;
00524 struct ast_datastore *datastore = NULL;
00525 char *parse, *filename_tmp = NULL, *filename = NULL, tmp[2] = "", dtmf_terminator = '#';
00526 const char *tmp2 = NULL;
00527 struct ast_flags options = { 0 };
00528 AST_DECLARE_APP_ARGS(args,
00529 AST_APP_ARG(soundfile);
00530 AST_APP_ARG(timeout);
00531 AST_APP_ARG(options);
00532 );
00533
00534 parse = ast_strdupa(data);
00535 AST_STANDARD_APP_ARGS(args, parse);
00536
00537 if (speech == NULL)
00538 return -1;
00539
00540 if (!ast_strlen_zero(args.options)) {
00541 char *options_buf = ast_strdupa(args.options);
00542 ast_app_parse_options(speech_background_options, &options, NULL, options_buf);
00543 }
00544
00545
00546 if (chan->_state != AST_STATE_UP && !ast_test_flag(&options, SB_OPT_NOANSWER)
00547 && ast_answer(chan)) {
00548 return -1;
00549 }
00550
00551
00552 oldreadformat = chan->readformat;
00553
00554
00555 if (ast_set_read_format(chan, speech->format))
00556 return -1;
00557
00558 if (!ast_strlen_zero(args.soundfile)) {
00559
00560 filename_tmp = ast_strdupa(args.soundfile);
00561 if (!ast_strlen_zero(args.timeout)) {
00562 if ((timeout = atof(args.timeout) * 1000.0) == 0)
00563 timeout = -1;
00564 } else
00565 timeout = 0;
00566 }
00567
00568
00569 ast_channel_lock(chan);
00570 if ((tmp2 = pbx_builtin_getvar_helper(chan, "SPEECH_DTMF_MAXLEN")) && !ast_strlen_zero(tmp2)) {
00571 max_dtmf_len = atoi(tmp2);
00572 }
00573
00574
00575 if ((tmp2 = pbx_builtin_getvar_helper(chan, "SPEECH_DTMF_TERMINATOR"))) {
00576 if (ast_strlen_zero(tmp2))
00577 dtmf_terminator = '\0';
00578 else
00579 dtmf_terminator = tmp2[0];
00580 }
00581 ast_channel_unlock(chan);
00582
00583
00584 if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
00585 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
00586 ast_speech_start(speech);
00587 }
00588
00589
00590 ast_stopstream(chan);
00591
00592
00593 while (done == 0) {
00594
00595 if (!quieted && (chan->streamid == -1 && chan->timingfunc == NULL) && (filename = strsep(&filename_tmp, "&"))) {
00596
00597 ast_stopstream(chan);
00598
00599 speech_streamfile(chan, filename, chan->language);
00600 }
00601
00602
00603 ast_sched_runq(chan->sched);
00604
00605
00606 res = ast_sched_wait(chan->sched);
00607 if (res < 0)
00608 res = 1000;
00609
00610
00611 if (ast_waitfor(chan, res) > 0) {
00612 f = ast_read(chan);
00613 if (f == NULL) {
00614
00615 done = 3;
00616 break;
00617 }
00618 }
00619
00620
00621 if ((!quieted || strlen(dtmf)) && started == 1) {
00622 current = ast_tvnow();
00623 if ((ast_tvdiff_ms(current, start)) >= timeout) {
00624 done = 1;
00625 if (f)
00626 ast_frfree(f);
00627 break;
00628 }
00629 }
00630
00631
00632 ast_mutex_lock(&speech->lock);
00633 if (ast_test_flag(speech, AST_SPEECH_QUIET)) {
00634 if (chan->stream)
00635 ast_stopstream(chan);
00636 ast_clear_flag(speech, AST_SPEECH_QUIET);
00637 quieted = 1;
00638 }
00639
00640 switch (speech->state) {
00641 case AST_SPEECH_STATE_READY:
00642
00643 if (chan->streamid == -1 && chan->timingfunc == NULL)
00644 ast_stopstream(chan);
00645 if (!quieted && chan->stream == NULL && timeout && started == 0 && !filename_tmp) {
00646 if (timeout == -1) {
00647 done = 1;
00648 if (f)
00649 ast_frfree(f);
00650 break;
00651 }
00652 start = ast_tvnow();
00653 started = 1;
00654 }
00655
00656 if (!strlen(dtmf) && f != NULL && f->frametype == AST_FRAME_VOICE) {
00657 ast_speech_write(speech, f->data.ptr, f->datalen);
00658 }
00659 break;
00660 case AST_SPEECH_STATE_WAIT:
00661
00662 if (!strlen(dtmf)) {
00663 if (chan->stream == NULL) {
00664 if (speech->processing_sound != NULL) {
00665 if (strlen(speech->processing_sound) > 0 && strcasecmp(speech->processing_sound, "none")) {
00666 speech_streamfile(chan, speech->processing_sound, chan->language);
00667 }
00668 }
00669 } else if (chan->streamid == -1 && chan->timingfunc == NULL) {
00670 ast_stopstream(chan);
00671 if (speech->processing_sound != NULL) {
00672 if (strlen(speech->processing_sound) > 0 && strcasecmp(speech->processing_sound, "none")) {
00673 speech_streamfile(chan, speech->processing_sound, chan->language);
00674 }
00675 }
00676 }
00677 }
00678 break;
00679 case AST_SPEECH_STATE_DONE:
00680
00681 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
00682 if (!strlen(dtmf)) {
00683
00684 speech->results = ast_speech_results_get(speech);
00685
00686 done = 1;
00687
00688 if (chan->stream != NULL) {
00689 ast_stopstream(chan);
00690 }
00691 }
00692 break;
00693 default:
00694 break;
00695 }
00696 ast_mutex_unlock(&speech->lock);
00697
00698
00699 if (f != NULL) {
00700
00701 switch (f->frametype) {
00702 case AST_FRAME_DTMF:
00703 if (dtmf_terminator != '\0' && f->subclass == dtmf_terminator) {
00704 done = 1;
00705 } else {
00706 if (chan->stream != NULL) {
00707 ast_stopstream(chan);
00708 }
00709 if (!started) {
00710
00711 timeout = (chan->pbx && chan->pbx->dtimeoutms) ? chan->pbx->dtimeoutms : 5000;
00712 started = 1;
00713 }
00714 start = ast_tvnow();
00715 snprintf(tmp, sizeof(tmp), "%c", f->subclass);
00716 strncat(dtmf, tmp, sizeof(dtmf) - strlen(dtmf) - 1);
00717
00718 if (max_dtmf_len && strlen(dtmf) == max_dtmf_len)
00719 done = 1;
00720 }
00721 break;
00722 case AST_FRAME_CONTROL:
00723 switch (f->subclass) {
00724 case AST_CONTROL_HANGUP:
00725
00726 done = 3;
00727 default:
00728 break;
00729 }
00730 default:
00731 break;
00732 }
00733 ast_frfree(f);
00734 f = NULL;
00735 }
00736 }
00737
00738 if (!ast_strlen_zero(dtmf)) {
00739
00740 speech->results = ast_calloc(1, sizeof(*speech->results));
00741 if (speech->results != NULL) {
00742 ast_speech_dtmf(speech, dtmf);
00743 speech->results->score = 1000;
00744 speech->results->text = ast_strdup(dtmf);
00745 speech->results->grammar = ast_strdup("dtmf");
00746 }
00747 ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
00748 }
00749
00750
00751 if (done == 3) {
00752
00753 ast_speech_destroy(speech);
00754 datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL);
00755 if (datastore != NULL)
00756 ast_channel_datastore_remove(chan, datastore);
00757 } else {
00758
00759 ast_set_read_format(chan, oldreadformat);
00760 }
00761
00762 return 0;
00763 }
00764
00765
00766
00767 static int speech_destroy(struct ast_channel *chan, void *data)
00768 {
00769 int res = 0;
00770 struct ast_speech *speech = find_speech(chan);
00771 struct ast_datastore *datastore = NULL;
00772
00773 if (speech == NULL)
00774 return -1;
00775
00776
00777 ast_speech_destroy(speech);
00778
00779 datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL);
00780 if (datastore != NULL) {
00781 ast_channel_datastore_remove(chan, datastore);
00782 }
00783
00784 return res;
00785 }
00786
00787 static int unload_module(void)
00788 {
00789 int res = 0;
00790
00791 res = ast_unregister_application("SpeechCreate");
00792 res |= ast_unregister_application("SpeechLoadGrammar");
00793 res |= ast_unregister_application("SpeechUnloadGrammar");
00794 res |= ast_unregister_application("SpeechActivateGrammar");
00795 res |= ast_unregister_application("SpeechDeactivateGrammar");
00796 res |= ast_unregister_application("SpeechStart");
00797 res |= ast_unregister_application("SpeechBackground");
00798 res |= ast_unregister_application("SpeechDestroy");
00799 res |= ast_unregister_application("SpeechProcessingSound");
00800 res |= ast_custom_function_unregister(&speech_function);
00801 res |= ast_custom_function_unregister(&speech_score_function);
00802 res |= ast_custom_function_unregister(&speech_text_function);
00803 res |= ast_custom_function_unregister(&speech_grammar_function);
00804 res |= ast_custom_function_unregister(&speech_engine_function);
00805 res |= ast_custom_function_unregister(&speech_results_type_function);
00806
00807 return res;
00808 }
00809
00810 static int load_module(void)
00811 {
00812 int res = 0;
00813
00814 res = ast_register_application("SpeechCreate", speech_create, "Create a Speech Structure", speechcreate_descrip);
00815 res |= ast_register_application("SpeechLoadGrammar", speech_load, "Load a Grammar", speechload_descrip);
00816 res |= ast_register_application("SpeechUnloadGrammar", speech_unload, "Unload a Grammar", speechunload_descrip);
00817 res |= ast_register_application("SpeechActivateGrammar", speech_activate, "Activate a Grammar", speechactivategrammar_descrip);
00818 res |= ast_register_application("SpeechDeactivateGrammar", speech_deactivate, "Deactivate a Grammar", speechdeactivategrammar_descrip);
00819 res |= ast_register_application("SpeechStart", speech_start, "Start recognizing voice in the audio stream", speechstart_descrip);
00820 res |= ast_register_application("SpeechBackground", speech_background, "Play a sound file and wait for speech to be recognized", speechbackground_descrip);
00821 res |= ast_register_application("SpeechDestroy", speech_destroy, "End speech recognition", speechdestroy_descrip);
00822 res |= ast_register_application("SpeechProcessingSound", speech_processing_sound, "Change background processing sound", speechprocessingsound_descrip);
00823 res |= ast_custom_function_register(&speech_function);
00824 res |= ast_custom_function_register(&speech_score_function);
00825 res |= ast_custom_function_register(&speech_text_function);
00826 res |= ast_custom_function_register(&speech_grammar_function);
00827 res |= ast_custom_function_register(&speech_engine_function);
00828 res |= ast_custom_function_register(&speech_results_type_function);
00829
00830 return res;
00831 }
00832
00833 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialplan Speech Applications");