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: 368751 $");
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, const struct ast_format_cap *cap)
00177 {
00178 struct ast_speech_engine *engine = NULL;
00179 struct ast_speech *new_speech = NULL;
00180 struct ast_format_cap *joint = NULL;
00181 struct ast_format best;
00182
00183 ast_format_set(&best, AST_FORMAT_SLINEAR, 0);
00184
00185
00186 if (!(engine = find_engine(engine_name)))
00187 return NULL;
00188
00189
00190 if ((joint = ast_format_cap_joint(engine->formats, cap))) {
00191 ast_best_codec(joint, &best);
00192 joint = ast_format_cap_destroy(joint);
00193 } else if (!ast_format_cap_iscompatible(engine->formats, &best)) {
00194 return NULL;
00195 }
00196
00197
00198 if (!(new_speech = ast_calloc(1, sizeof(*new_speech))))
00199 return NULL;
00200
00201
00202 ast_mutex_init(&new_speech->lock);
00203
00204
00205 new_speech->results = NULL;
00206
00207
00208 new_speech->engine = engine;
00209
00210
00211 ast_format_copy(&new_speech->format, &best);
00212
00213
00214 ast_speech_change_state(new_speech, AST_SPEECH_STATE_NOT_READY);
00215
00216
00217 if (engine->create(new_speech, &best)) {
00218 ast_mutex_destroy(&new_speech->lock);
00219 ast_free(new_speech);
00220 new_speech = NULL;
00221 }
00222
00223 return new_speech;
00224 }
00225
00226
00227 int ast_speech_destroy(struct ast_speech *speech)
00228 {
00229 int res = 0;
00230
00231
00232 speech->engine->destroy(speech);
00233
00234
00235 ast_mutex_destroy(&speech->lock);
00236
00237
00238 if (speech->results)
00239 ast_speech_results_free(speech->results);
00240
00241
00242 if (speech->processing_sound)
00243 ast_free(speech->processing_sound);
00244
00245
00246 ast_free(speech);
00247
00248 return res;
00249 }
00250
00251
00252 int ast_speech_change_state(struct ast_speech *speech, int state)
00253 {
00254 int res = 0;
00255
00256 switch (state) {
00257 case AST_SPEECH_STATE_WAIT:
00258
00259 ast_set_flag(speech, AST_SPEECH_SPOKE);
00260 default:
00261 speech->state = state;
00262 break;
00263 }
00264
00265 return res;
00266 }
00267
00268
00269 int ast_speech_change_results_type(struct ast_speech *speech, enum ast_speech_results_type results_type)
00270 {
00271 speech->results_type = results_type;
00272
00273 return (speech->engine->change_results_type ? speech->engine->change_results_type(speech, results_type) : 0);
00274 }
00275
00276
00277 int ast_speech_register(struct ast_speech_engine *engine)
00278 {
00279 int res = 0;
00280
00281
00282 if (!engine->create || !engine->write || !engine->destroy) {
00283 ast_log(LOG_WARNING, "Speech recognition engine '%s' did not meet minimum API requirements.\n", engine->name);
00284 return -1;
00285 }
00286
00287
00288 if (find_engine(engine->name)) {
00289 ast_log(LOG_WARNING, "Speech recognition engine '%s' already exists.\n", engine->name);
00290 return -1;
00291 }
00292
00293 ast_verb(2, "Registered speech recognition engine '%s'\n", engine->name);
00294
00295
00296 AST_RWLIST_WRLOCK(&engines);
00297 AST_RWLIST_INSERT_HEAD(&engines, engine, list);
00298 if (!default_engine) {
00299 default_engine = engine;
00300 ast_verb(2, "Made '%s' the default speech recognition engine\n", engine->name);
00301 }
00302 AST_RWLIST_UNLOCK(&engines);
00303
00304 return res;
00305 }
00306
00307
00308 int ast_speech_unregister(const char *engine_name)
00309 {
00310 struct ast_speech_engine *engine = NULL;
00311 int res = -1;
00312
00313 if (ast_strlen_zero(engine_name))
00314 return -1;
00315
00316 AST_RWLIST_WRLOCK(&engines);
00317 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&engines, engine, list) {
00318 if (!strcasecmp(engine->name, engine_name)) {
00319
00320 AST_RWLIST_REMOVE_CURRENT(list);
00321
00322 if (engine == default_engine) {
00323 default_engine = AST_RWLIST_FIRST(&engines);
00324 }
00325 ast_verb(2, "Unregistered speech recognition engine '%s'\n", engine_name);
00326
00327 res = 0;
00328 break;
00329 }
00330 }
00331 AST_RWLIST_TRAVERSE_SAFE_END;
00332 AST_RWLIST_UNLOCK(&engines);
00333
00334 return res;
00335 }
00336
00337 static int unload_module(void)
00338 {
00339
00340 return -1;
00341 }
00342
00343 static int load_module(void)
00344 {
00345 return AST_MODULE_LOAD_SUCCESS;
00346 }
00347
00348 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Generic Speech Recognition API",
00349 .load = load_module,
00350 .unload = unload_module,
00351 .load_pri = AST_MODPRI_APP_DEPEND,
00352 );