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: 247845 $");
00029
00030 #include "asterisk/channel.h"
00031 #include "asterisk/module.h"
00032 #include "asterisk/lock.h"
00033 #include "asterisk/linkedlists.h"
00034 #include "asterisk/cli.h"
00035 #include "asterisk/term.h"
00036 #include "asterisk/speech.h"
00037
00038
00039 static AST_RWLIST_HEAD_STATIC(engines, ast_speech_engine);
00040 static struct ast_speech_engine *default_engine = NULL;
00041
00042
00043 static struct ast_speech_engine *find_engine(char *engine_name)
00044 {
00045 struct ast_speech_engine *engine = NULL;
00046
00047
00048 if (ast_strlen_zero(engine_name))
00049 return default_engine;
00050
00051 AST_RWLIST_RDLOCK(&engines);
00052 AST_RWLIST_TRAVERSE(&engines, engine, list) {
00053 if (!strcasecmp(engine->name, engine_name)) {
00054 break;
00055 }
00056 }
00057 AST_RWLIST_UNLOCK(&engines);
00058
00059 return engine;
00060 }
00061
00062
00063 int ast_speech_grammar_activate(struct ast_speech *speech, char *grammar_name)
00064 {
00065 return (speech->engine->activate ? speech->engine->activate(speech, grammar_name) : -1);
00066 }
00067
00068
00069 int ast_speech_grammar_deactivate(struct ast_speech *speech, char *grammar_name)
00070 {
00071 return (speech->engine->deactivate ? speech->engine->deactivate(speech, grammar_name) : -1);
00072 }
00073
00074
00075 int ast_speech_grammar_load(struct ast_speech *speech, char *grammar_name, char *grammar)
00076 {
00077 return (speech->engine->load ? speech->engine->load(speech, grammar_name, grammar) : -1);
00078 }
00079
00080
00081 int ast_speech_grammar_unload(struct ast_speech *speech, char *grammar_name)
00082 {
00083 return (speech->engine->unload ? speech->engine->unload(speech, grammar_name) : -1);
00084 }
00085
00086
00087 struct ast_speech_result *ast_speech_results_get(struct ast_speech *speech)
00088 {
00089 return (speech->engine->get ? speech->engine->get(speech) : NULL);
00090 }
00091
00092
00093 int ast_speech_results_free(struct ast_speech_result *result)
00094 {
00095 struct ast_speech_result *current_result = result, *prev_result = NULL;
00096 int res = 0;
00097
00098 while (current_result != NULL) {
00099 prev_result = current_result;
00100
00101 if (current_result->text != NULL) {
00102 ast_free(current_result->text);
00103 current_result->text = NULL;
00104 }
00105 if (current_result->grammar != NULL) {
00106 ast_free(current_result->grammar);
00107 current_result->grammar = NULL;
00108 }
00109
00110 current_result = AST_LIST_NEXT(current_result, list);
00111 ast_free(prev_result);
00112 prev_result = NULL;
00113 }
00114
00115 return res;
00116 }
00117
00118
00119 void ast_speech_start(struct ast_speech *speech)
00120 {
00121
00122
00123 ast_clear_flag(speech, AST_SPEECH_SPOKE);
00124 ast_clear_flag(speech, AST_SPEECH_QUIET);
00125 ast_clear_flag(speech, AST_SPEECH_HAVE_RESULTS);
00126
00127
00128 if (speech->results) {
00129 ast_speech_results_free(speech->results);
00130 speech->results = NULL;
00131 }
00132
00133
00134 if (speech->engine->start)
00135 speech->engine->start(speech);
00136
00137 return;
00138 }
00139
00140
00141 int ast_speech_write(struct ast_speech *speech, void *data, int len)
00142 {
00143
00144 if (speech->state != AST_SPEECH_STATE_READY)
00145 return -1;
00146
00147 return speech->engine->write(speech, data, len);
00148 }
00149
00150
00151 int ast_speech_dtmf(struct ast_speech *speech, const char *dtmf)
00152 {
00153 int res = 0;
00154
00155 if (speech->state != AST_SPEECH_STATE_READY)
00156 return -1;
00157
00158 if (speech->engine->dtmf != NULL) {
00159 res = speech->engine->dtmf(speech, dtmf);
00160 }
00161
00162 return res;
00163 }
00164
00165
00166 int ast_speech_change(struct ast_speech *speech, char *name, const char *value)
00167 {
00168 return (speech->engine->change ? speech->engine->change(speech, name, value) : -1);
00169 }
00170
00171
00172 struct ast_speech *ast_speech_new(char *engine_name, int formats)
00173 {
00174 struct ast_speech_engine *engine = NULL;
00175 struct ast_speech *new_speech = NULL;
00176 int format = AST_FORMAT_SLINEAR;
00177
00178
00179 if (!(engine = find_engine(engine_name)))
00180 return NULL;
00181
00182
00183 if ((format = (engine->formats & formats)))
00184 format = ast_best_codec(format);
00185 else if ((engine->formats & AST_FORMAT_SLINEAR))
00186 format = AST_FORMAT_SLINEAR;
00187 else
00188 return NULL;
00189
00190
00191 if (!(new_speech = ast_calloc(1, sizeof(*new_speech))))
00192 return NULL;
00193
00194
00195 ast_mutex_init(&new_speech->lock);
00196
00197
00198 new_speech->results = NULL;
00199
00200
00201 new_speech->engine = engine;
00202
00203
00204 new_speech->format = format;
00205
00206
00207 ast_speech_change_state(new_speech, AST_SPEECH_STATE_NOT_READY);
00208
00209
00210 if (engine->create(new_speech, format)) {
00211 ast_mutex_destroy(&new_speech->lock);
00212 ast_free(new_speech);
00213 new_speech = NULL;
00214 }
00215
00216 return new_speech;
00217 }
00218
00219
00220 int ast_speech_destroy(struct ast_speech *speech)
00221 {
00222 int res = 0;
00223
00224
00225 speech->engine->destroy(speech);
00226
00227
00228 ast_mutex_destroy(&speech->lock);
00229
00230
00231 if (speech->results)
00232 ast_speech_results_free(speech->results);
00233
00234
00235 if (speech->processing_sound)
00236 ast_free(speech->processing_sound);
00237
00238
00239 ast_free(speech);
00240
00241 return res;
00242 }
00243
00244
00245 int ast_speech_change_state(struct ast_speech *speech, int state)
00246 {
00247 int res = 0;
00248
00249 switch (state) {
00250 case AST_SPEECH_STATE_WAIT:
00251
00252 ast_set_flag(speech, AST_SPEECH_SPOKE);
00253 default:
00254 speech->state = state;
00255 break;
00256 }
00257
00258 return res;
00259 }
00260
00261
00262 int ast_speech_change_results_type(struct ast_speech *speech, enum ast_speech_results_type results_type)
00263 {
00264 speech->results_type = results_type;
00265
00266 return (speech->engine->change_results_type ? speech->engine->change_results_type(speech, results_type) : 0);
00267 }
00268
00269
00270 int ast_speech_register(struct ast_speech_engine *engine)
00271 {
00272 struct ast_speech_engine *existing_engine = NULL;
00273 int res = 0;
00274
00275
00276 if (!engine->create || !engine->write || !engine->destroy) {
00277 ast_log(LOG_WARNING, "Speech recognition engine '%s' did not meet minimum API requirements.\n", engine->name);
00278 return -1;
00279 }
00280
00281
00282 if ((existing_engine = find_engine(engine->name))) {
00283 ast_log(LOG_WARNING, "Speech recognition engine '%s' already exists.\n", engine->name);
00284 return -1;
00285 }
00286
00287 ast_verb(2, "Registered speech recognition engine '%s'\n", engine->name);
00288
00289
00290 AST_RWLIST_WRLOCK(&engines);
00291 AST_RWLIST_INSERT_HEAD(&engines, engine, list);
00292 if (!default_engine) {
00293 default_engine = engine;
00294 ast_verb(2, "Made '%s' the default speech recognition engine\n", engine->name);
00295 }
00296 AST_RWLIST_UNLOCK(&engines);
00297
00298 return res;
00299 }
00300
00301
00302 int ast_speech_unregister(char *engine_name)
00303 {
00304 struct ast_speech_engine *engine = NULL;
00305 int res = -1;
00306
00307 if (ast_strlen_zero(engine_name))
00308 return -1;
00309
00310 AST_RWLIST_WRLOCK(&engines);
00311 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&engines, engine, list) {
00312 if (!strcasecmp(engine->name, engine_name)) {
00313
00314 AST_RWLIST_REMOVE_CURRENT(list);
00315
00316 if (engine == default_engine) {
00317 default_engine = AST_RWLIST_FIRST(&engines);
00318 }
00319 ast_verb(2, "Unregistered speech recognition engine '%s'\n", engine_name);
00320
00321 res = 0;
00322 break;
00323 }
00324 }
00325 AST_RWLIST_TRAVERSE_SAFE_END;
00326 AST_RWLIST_UNLOCK(&engines);
00327
00328 return res;
00329 }
00330
00331 static int unload_module(void)
00332 {
00333
00334 return -1;
00335 }
00336
00337 static int load_module(void)
00338 {
00339 return AST_MODULE_LOAD_SUCCESS;
00340 }
00341
00342 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Generic Speech Recognition API",
00343 .load = load_module,
00344 .unload = unload_module,
00345 );