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