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