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: 77831 $");
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 && ast_test_flag(speech, AST_SPEECH_HAVE_RESULTS)) {
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_change(struct ast_speech *speech, char *name, const char *value)
00198 {
00199 int res = 0;
00200
00201 if (speech->engine->change != NULL) {
00202 res = speech->engine->change(speech, name, value);
00203 }
00204
00205 return res;
00206 }
00207
00208
00209 struct ast_speech *ast_speech_new(char *engine_name, int format)
00210 {
00211 struct ast_speech_engine *engine = NULL;
00212 struct ast_speech *new_speech = NULL;
00213
00214
00215 engine = find_engine(engine_name);
00216 if (engine == NULL) {
00217
00218 return NULL;
00219 }
00220
00221
00222 new_speech = ast_calloc(1, sizeof(*new_speech));
00223 if (new_speech == NULL) {
00224
00225 return NULL;
00226 }
00227
00228
00229 ast_mutex_init(&new_speech->lock);
00230
00231
00232 new_speech->results = NULL;
00233
00234
00235 new_speech->engine = engine;
00236
00237
00238 ast_speech_change_state(new_speech, AST_SPEECH_STATE_NOT_READY);
00239
00240
00241 if (engine->create(new_speech)) {
00242 ast_mutex_destroy(&new_speech->lock);
00243 free(new_speech);
00244 new_speech = NULL;
00245 }
00246
00247 return new_speech;
00248 }
00249
00250
00251 int ast_speech_destroy(struct ast_speech *speech)
00252 {
00253 int res = 0;
00254
00255
00256 speech->engine->destroy(speech);
00257
00258
00259 ast_mutex_destroy(&speech->lock);
00260
00261
00262 if (speech->results != NULL) {
00263 ast_speech_results_free(speech->results);
00264 speech->results = NULL;
00265 }
00266
00267
00268 if (speech->processing_sound != NULL) {
00269 free(speech->processing_sound);
00270 speech->processing_sound = NULL;
00271 }
00272
00273
00274 free(speech);
00275 speech = NULL;
00276
00277 return res;
00278 }
00279
00280
00281 int ast_speech_change_state(struct ast_speech *speech, int state)
00282 {
00283 int res = 0;
00284
00285 switch (state) {
00286 case AST_SPEECH_STATE_WAIT:
00287
00288 ast_set_flag(speech, AST_SPEECH_SPOKE);
00289 default:
00290 speech->state = state;
00291 break;
00292 }
00293
00294 return res;
00295 }
00296
00297
00298 int ast_speech_change_results_type(struct ast_speech *speech, enum ast_speech_results_type results_type)
00299 {
00300 int res = 0;
00301
00302 speech->results_type = results_type;
00303
00304 if (speech->engine->change_results_type)
00305 res = speech->engine->change_results_type(speech, results_type);
00306
00307 return res;
00308 }
00309
00310
00311 int ast_speech_register(struct ast_speech_engine *engine)
00312 {
00313 struct ast_speech_engine *existing_engine = NULL;
00314 int res = 0;
00315
00316 existing_engine = find_engine(engine->name);
00317 if (existing_engine != NULL) {
00318
00319 return -1;
00320 }
00321
00322 if (option_verbose > 1)
00323 ast_verbose(VERBOSE_PREFIX_2 "Registered speech recognition engine '%s'\n", engine->name);
00324
00325
00326 AST_LIST_LOCK(&engines);
00327 AST_LIST_INSERT_HEAD(&engines, engine, list);
00328 if (default_engine == NULL) {
00329 default_engine = engine;
00330 if (option_verbose > 1)
00331 ast_verbose(VERBOSE_PREFIX_2 "Made '%s' the default speech recognition engine\n", engine->name);
00332 }
00333 AST_LIST_UNLOCK(&engines);
00334
00335 return res;
00336 }
00337
00338
00339 int ast_speech_unregister(char *engine_name)
00340 {
00341 struct ast_speech_engine *engine = NULL;
00342 int res = -1;
00343
00344 if (engine_name == NULL) {
00345 return res;
00346 }
00347
00348 AST_LIST_LOCK(&engines);
00349 AST_LIST_TRAVERSE_SAFE_BEGIN(&engines, engine, list) {
00350 if (!strcasecmp(engine->name, engine_name)) {
00351
00352 AST_LIST_REMOVE_CURRENT(&engines, list);
00353
00354 if (default_engine == engine) {
00355 default_engine = AST_LIST_FIRST(&engines);
00356 }
00357 if (option_verbose > 1)
00358 ast_verbose(VERBOSE_PREFIX_2 "Unregistered speech recognition engine '%s'\n", engine_name);
00359
00360 res = 0;
00361 break;
00362 }
00363 }
00364 AST_LIST_TRAVERSE_SAFE_END
00365 AST_LIST_UNLOCK(&engines);
00366
00367 return res;
00368 }
00369
00370 static int unload_module(void)
00371 {
00372
00373 return -1;
00374 }
00375
00376 static int load_module(void)
00377 {
00378 int res = 0;
00379
00380
00381 AST_LIST_HEAD_INIT_NOLOCK(&engines);
00382
00383 return res;
00384 }
00385
00386 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Generic Speech Recognition API",
00387 .load = load_module,
00388 .unload = unload_module,
00389 );