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