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 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 81406 $");
00029
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <unistd.h>
00033 #include <string.h>
00034
00035 #include "asterisk/channel.h"
00036 #include "asterisk/module.h"
00037 #include "asterisk/lock.h"
00038 #include "asterisk/linkedlists.h"
00039 #include "asterisk/cli.h"
00040 #include "asterisk/term.h"
00041 #include "asterisk/options.h"
00042 #include "asterisk/speech.h"
00043
00044
00045 static AST_LIST_HEAD_STATIC(engines, ast_speech_engine);
00046 static struct ast_speech_engine *default_engine = NULL;
00047
00048
00049 static struct ast_speech_engine *find_engine(char *engine_name)
00050 {
00051 struct ast_speech_engine *engine = NULL;
00052
00053
00054 if (engine_name == NULL || strlen(engine_name) == 0) {
00055 return default_engine;
00056 }
00057
00058 AST_LIST_LOCK(&engines);
00059 AST_LIST_TRAVERSE_SAFE_BEGIN(&engines, engine, list) {
00060 if (!strcasecmp(engine->name, engine_name)) {
00061 break;
00062 }
00063 }
00064 AST_LIST_TRAVERSE_SAFE_END
00065 AST_LIST_UNLOCK(&engines);
00066
00067 return engine;
00068 }
00069
00070
00071 int ast_speech_grammar_activate(struct ast_speech *speech, char *grammar_name)
00072 {
00073 int res = 0;
00074
00075 if (speech->engine->activate != NULL) {
00076 res = speech->engine->activate(speech, grammar_name);
00077 }
00078
00079 return res;
00080 }
00081
00082
00083 int ast_speech_grammar_deactivate(struct ast_speech *speech, char *grammar_name)
00084 {
00085 int res = 0;
00086
00087 if (speech->engine->deactivate != NULL) {
00088 res = speech->engine->deactivate(speech, grammar_name);
00089 }
00090
00091 return res;
00092 }
00093
00094
00095 int ast_speech_grammar_load(struct ast_speech *speech, char *grammar_name, char *grammar)
00096 {
00097 int res = 0;
00098
00099 if (speech->engine->load != NULL) {
00100 res = speech->engine->load(speech, grammar_name, grammar);
00101 }
00102
00103 return res;
00104 }
00105
00106
00107 int ast_speech_grammar_unload(struct ast_speech *speech, char *grammar_name)
00108 {
00109 int res = 0;
00110
00111 if (speech->engine->unload != NULL) {
00112 res = speech->engine->unload(speech, grammar_name);
00113 }
00114
00115 return res;
00116 }
00117
00118
00119 struct ast_speech_result *ast_speech_results_get(struct ast_speech *speech)
00120 {
00121 struct ast_speech_result *result = NULL;
00122
00123 if (speech->engine->get != NULL) {
00124 result = speech->engine->get(speech);
00125 }
00126
00127 return result;
00128 }
00129
00130
00131 int ast_speech_results_free(struct ast_speech_result *result)
00132 {
00133 struct ast_speech_result *current_result = result, *prev_result = NULL;
00134 int res = 0;
00135
00136 while (current_result != NULL) {
00137 prev_result = current_result;
00138
00139 if (current_result->text != NULL) {
00140 free(current_result->text);
00141 current_result->text = NULL;
00142 }
00143 if (current_result->grammar != NULL) {
00144 free(current_result->grammar);
00145 current_result->grammar = NULL;
00146 }
00147
00148 current_result = current_result->next;
00149 free(prev_result);
00150 prev_result = NULL;
00151 }
00152
00153 return res;
00154 }
00155
00156
00157 void ast_speech_start(struct ast_speech *speech)
00158 {
00159
00160
00161 ast_clear_flag(speech, AST_SPEECH_SPOKE);
00162 ast_clear_flag(speech, AST_SPEECH_QUIET);
00163 ast_clear_flag(speech, AST_SPEECH_HAVE_RESULTS);
00164
00165
00166 if (speech->results != NULL) {
00167 ast_speech_results_free(speech->results);
00168 speech->results = NULL;
00169 }
00170
00171
00172 if (speech->engine->start != NULL) {
00173 speech->engine->start(speech);
00174 }
00175
00176 return;
00177 }
00178
00179
00180 int ast_speech_write(struct ast_speech *speech, void *data, int len)
00181 {
00182 int res = 0;
00183
00184
00185 if (speech->state != AST_SPEECH_STATE_READY) {
00186 return -1;
00187 }
00188
00189 if (speech->engine->write != NULL) {
00190 speech->engine->write(speech, data, len);
00191 }
00192
00193 return res;
00194 }
00195
00196
00197 int ast_speech_dtmf(struct ast_speech *speech, const char *dtmf)
00198 {
00199 int res = 0;
00200
00201 if (speech->state != AST_SPEECH_STATE_READY)
00202 return -1;
00203
00204 if (speech->engine->dtmf != NULL) {
00205 res = speech->engine->dtmf(speech, dtmf);
00206 }
00207
00208 return res;
00209 }
00210
00211
00212 int ast_speech_change(struct ast_speech *speech, char *name, const char *value)
00213 {
00214 int res = 0;
00215
00216 if (speech->engine->change != NULL) {
00217 res = speech->engine->change(speech, name, value);
00218 }
00219
00220 return res;
00221 }
00222
00223
00224 struct ast_speech *ast_speech_new(char *engine_name, int format)
00225 {
00226 struct ast_speech_engine *engine = NULL;
00227 struct ast_speech *new_speech = NULL;
00228
00229
00230 engine = find_engine(engine_name);
00231 if (engine == NULL) {
00232
00233 return NULL;
00234 }
00235
00236
00237 new_speech = ast_calloc(1, sizeof(*new_speech));
00238 if (new_speech == NULL) {
00239
00240 return NULL;
00241 }
00242
00243
00244 ast_mutex_init(&new_speech->lock);
00245
00246
00247 new_speech->results = NULL;
00248
00249
00250 new_speech->engine = engine;
00251
00252
00253 ast_speech_change_state(new_speech, AST_SPEECH_STATE_NOT_READY);
00254
00255
00256 if (engine->create(new_speech)) {
00257 ast_mutex_destroy(&new_speech->lock);
00258 free(new_speech);
00259 new_speech = NULL;
00260 }
00261
00262 return new_speech;
00263 }
00264
00265
00266 int ast_speech_destroy(struct ast_speech *speech)
00267 {
00268 int res = 0;
00269
00270
00271 speech->engine->destroy(speech);
00272
00273
00274 ast_mutex_destroy(&speech->lock);
00275
00276
00277 if (speech->results != NULL) {
00278 ast_speech_results_free(speech->results);
00279 speech->results = NULL;
00280 }
00281
00282
00283 if (speech->processing_sound != NULL) {
00284 free(speech->processing_sound);
00285 speech->processing_sound = NULL;
00286 }
00287
00288
00289 free(speech);
00290 speech = NULL;
00291
00292 return res;
00293 }
00294
00295
00296 int ast_speech_change_state(struct ast_speech *speech, int state)
00297 {
00298 int res = 0;
00299
00300 switch (state) {
00301 case AST_SPEECH_STATE_WAIT:
00302
00303 ast_set_flag(speech, AST_SPEECH_SPOKE);
00304 default:
00305 speech->state = state;
00306 break;
00307 }
00308
00309 return res;
00310 }
00311
00312
00313 int ast_speech_change_results_type(struct ast_speech *speech, enum ast_speech_results_type results_type)
00314 {
00315 int res = 0;
00316
00317 speech->results_type = results_type;
00318
00319 if (speech->engine->change_results_type)
00320 res = speech->engine->change_results_type(speech, results_type);
00321
00322 return res;
00323 }
00324
00325
00326 int ast_speech_register(struct ast_speech_engine *engine)
00327 {
00328 struct ast_speech_engine *existing_engine = NULL;
00329 int res = 0;
00330
00331 existing_engine = find_engine(engine->name);
00332 if (existing_engine != NULL) {
00333
00334 return -1;
00335 }
00336
00337 if (option_verbose > 1)
00338 ast_verbose(VERBOSE_PREFIX_2 "Registered speech recognition engine '%s'\n", engine->name);
00339
00340
00341 AST_LIST_LOCK(&engines);
00342 AST_LIST_INSERT_HEAD(&engines, engine, list);
00343 if (default_engine == NULL) {
00344 default_engine = engine;
00345 if (option_verbose > 1)
00346 ast_verbose(VERBOSE_PREFIX_2 "Made '%s' the default speech recognition engine\n", engine->name);
00347 }
00348 AST_LIST_UNLOCK(&engines);
00349
00350 return res;
00351 }
00352
00353
00354 int ast_speech_unregister(char *engine_name)
00355 {
00356 struct ast_speech_engine *engine = NULL;
00357 int res = -1;
00358
00359 if (engine_name == NULL) {
00360 return res;
00361 }
00362
00363 AST_LIST_LOCK(&engines);
00364 AST_LIST_TRAVERSE_SAFE_BEGIN(&engines, engine, list) {
00365 if (!strcasecmp(engine->name, engine_name)) {
00366
00367 AST_LIST_REMOVE_CURRENT(&engines, list);
00368
00369 if (default_engine == engine) {
00370 default_engine = AST_LIST_FIRST(&engines);
00371 }
00372 if (option_verbose > 1)
00373 ast_verbose(VERBOSE_PREFIX_2 "Unregistered speech recognition engine '%s'\n", engine_name);
00374
00375 res = 0;
00376 break;
00377 }
00378 }
00379 AST_LIST_TRAVERSE_SAFE_END
00380 AST_LIST_UNLOCK(&engines);
00381
00382 return res;
00383 }
00384
00385 static int unload_module(void)
00386 {
00387
00388 return -1;
00389 }
00390
00391 static int load_module(void)
00392 {
00393 int res = 0;
00394
00395
00396 AST_LIST_HEAD_INIT_NOLOCK(&engines);
00397
00398 return res;
00399 }
00400
00401 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Generic Speech Recognition API",
00402 .load = load_module,
00403 .unload = unload_module,
00404 );