| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2006, Digium, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Joshua Colp <jcolp@digium.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							|  |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \file
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \brief Generic Speech Recognition API | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \author Joshua Colp <jcolp@digium.com> | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							|  |  |  | #include "asterisk/lock.h"
 | 
					
						
							|  |  |  | #include "asterisk/linkedlists.h"
 | 
					
						
							|  |  |  | #include "asterisk/cli.h"
 | 
					
						
							|  |  |  | #include "asterisk/term.h"
 | 
					
						
							|  |  |  | #include "asterisk/speech.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | static AST_RWLIST_HEAD_STATIC(engines, ast_speech_engine); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | static struct ast_speech_engine *default_engine = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Find a speech recognition engine of specified name, if NULL then use the default one */ | 
					
						
							| 
									
										
										
										
											2009-05-21 21:13:09 +00:00
										 |  |  | static struct ast_speech_engine *find_engine(const char *engine_name) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ast_speech_engine *engine = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* If no name is specified -- use the default engine */ | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	if (ast_strlen_zero(engine_name)) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 		return default_engine; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	AST_RWLIST_RDLOCK(&engines); | 
					
						
							|  |  |  | 	AST_RWLIST_TRAVERSE(&engines, engine, list) { | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 		if (!strcasecmp(engine->name, engine_name)) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	AST_RWLIST_UNLOCK(&engines); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return engine; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Activate a loaded (either local or global) grammar */ | 
					
						
							| 
									
										
										
										
											2009-05-21 21:13:09 +00:00
										 |  |  | int ast_speech_grammar_activate(struct ast_speech *speech, const char *grammar_name) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	return (speech->engine->activate ? speech->engine->activate(speech, grammar_name) : -1); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Deactivate a loaded grammar on a speech structure */ | 
					
						
							| 
									
										
										
										
											2009-05-21 21:13:09 +00:00
										 |  |  | int ast_speech_grammar_deactivate(struct ast_speech *speech, const char *grammar_name) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	return (speech->engine->deactivate ? speech->engine->deactivate(speech, grammar_name) : -1); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Load a local grammar on a speech structure */ | 
					
						
							| 
									
										
										
										
											2009-05-21 21:13:09 +00:00
										 |  |  | int ast_speech_grammar_load(struct ast_speech *speech, const char *grammar_name, const char *grammar) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	return (speech->engine->load ? speech->engine->load(speech, grammar_name, grammar) : -1); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Unload a local grammar from a speech structure */ | 
					
						
							| 
									
										
										
										
											2009-05-21 21:13:09 +00:00
										 |  |  | int ast_speech_grammar_unload(struct ast_speech *speech, const char *grammar_name) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	return (speech->engine->unload ? speech->engine->unload(speech, grammar_name) : -1); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Return the results of a recognition from the speech structure */ | 
					
						
							|  |  |  | struct ast_speech_result *ast_speech_results_get(struct ast_speech *speech) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-08-31 15:54:32 +00:00
										 |  |  | 	return (speech->engine->get ? speech->engine->get(speech) : NULL); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Free a list of results */ | 
					
						
							|  |  |  | int ast_speech_results_free(struct ast_speech_result *result) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_speech_result *current_result = result, *prev_result = NULL; | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (current_result != NULL) { | 
					
						
							|  |  |  | 		prev_result = current_result; | 
					
						
							|  |  |  | 		/* Deallocate what we can */ | 
					
						
							|  |  |  | 		if (current_result->text != NULL) { | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 			ast_free(current_result->text); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 			current_result->text = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-04-13 00:18:52 +00:00
										 |  |  | 		if (current_result->grammar != NULL) { | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 			ast_free(current_result->grammar); | 
					
						
							| 
									
										
										
										
											2006-04-13 00:18:52 +00:00
										 |  |  | 			current_result->grammar = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 		/* Move on and then free ourselves */ | 
					
						
							| 
									
										
										
										
											2007-07-11 17:34:30 +00:00
										 |  |  | 		current_result = AST_LIST_NEXT(current_result, list); | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(prev_result); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 		prev_result = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Start speech recognition on a speech structure */ | 
					
						
							|  |  |  | void ast_speech_start(struct ast_speech *speech) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-13 00:18:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Clear any flags that may affect things */ | 
					
						
							|  |  |  | 	ast_clear_flag(speech, AST_SPEECH_SPOKE); | 
					
						
							| 
									
										
										
										
											2006-10-13 21:07:06 +00:00
										 |  |  | 	ast_clear_flag(speech, AST_SPEECH_QUIET); | 
					
						
							| 
									
										
										
										
											2007-07-31 16:21:34 +00:00
										 |  |  | 	ast_clear_flag(speech, AST_SPEECH_HAVE_RESULTS); | 
					
						
							| 
									
										
										
										
											2006-04-13 00:18:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* If results are on the structure, free them since we are starting again */ | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	if (speech->results) { | 
					
						
							| 
									
										
										
										
											2006-04-13 00:18:52 +00:00
										 |  |  | 		ast_speech_results_free(speech->results); | 
					
						
							|  |  |  | 		speech->results = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 	/* If the engine needs to start stuff up, do it */ | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	if (speech->engine->start) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 		speech->engine->start(speech); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Write in signed linear audio to be recognized */ | 
					
						
							|  |  |  | int ast_speech_write(struct ast_speech *speech, void *data, int len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Make sure the speech engine is ready to accept audio */ | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	if (speech->state != AST_SPEECH_STATE_READY) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	return speech->engine->write(speech, data, len); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-13 14:55:17 +00:00
										 |  |  | /*! \brief Signal to the engine that DTMF was received */ | 
					
						
							| 
									
										
										
										
											2007-08-13 21:59:15 +00:00
										 |  |  | int ast_speech_dtmf(struct ast_speech *speech, const char *dtmf) | 
					
						
							| 
									
										
										
										
											2007-08-13 14:55:17 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (speech->state != AST_SPEECH_STATE_READY) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (speech->engine->dtmf != NULL) { | 
					
						
							|  |  |  | 		res = speech->engine->dtmf(speech, dtmf); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-07-18 16:22:26 +00:00
										 |  |  | /*! \brief Change an engine specific attribute */ | 
					
						
							| 
									
										
										
										
											2009-05-21 21:13:09 +00:00
										 |  |  | int ast_speech_change(struct ast_speech *speech, const char *name, const char *value) | 
					
						
							| 
									
										
										
										
											2006-07-18 16:22:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	return (speech->engine->change ? speech->engine->change(speech, name, value) : -1); | 
					
						
							| 
									
										
										
										
											2006-07-18 16:22:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | /*! \brief Create a new speech structure using the engine specified */ | 
					
						
							| 
									
										
										
										
											2009-05-21 21:13:09 +00:00
										 |  |  | struct ast_speech *ast_speech_new(const char *engine_name, int formats) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ast_speech_engine *engine = NULL; | 
					
						
							|  |  |  | 	struct ast_speech *new_speech = NULL; | 
					
						
							| 
									
										
										
										
											2007-07-11 16:19:00 +00:00
										 |  |  | 	int format = AST_FORMAT_SLINEAR; | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Try to find the speech recognition engine that was requested */ | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	if (!(engine = find_engine(engine_name))) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-11 16:19:00 +00:00
										 |  |  | 	/* Before even allocating the memory below do some codec negotiation, we choose the best codec possible and fall back to signed linear if possible */ | 
					
						
							|  |  |  | 	if ((format = (engine->formats & formats))) | 
					
						
							|  |  |  | 		format = ast_best_codec(format); | 
					
						
							|  |  |  | 	else if ((engine->formats & AST_FORMAT_SLINEAR)) | 
					
						
							|  |  |  | 		format = AST_FORMAT_SLINEAR; | 
					
						
							|  |  |  | 	else | 
					
						
							| 
									
										
										
										
											2007-07-11 16:10:03 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 	/* Allocate our own speech structure, and try to allocate a structure from the engine too */ | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	if (!(new_speech = ast_calloc(1, sizeof(*new_speech)))) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Initialize the lock */ | 
					
						
							|  |  |  | 	ast_mutex_init(&new_speech->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-13 00:18:52 +00:00
										 |  |  | 	/* Make sure no results are present */ | 
					
						
							|  |  |  | 	new_speech->results = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 	/* Copy over our engine pointer */ | 
					
						
							|  |  |  | 	new_speech->engine = engine; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-11 16:10:03 +00:00
										 |  |  | 	/* Can't forget the format audio is going to be in */ | 
					
						
							|  |  |  | 	new_speech->format = format; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 	/* We are not ready to accept audio yet */ | 
					
						
							|  |  |  | 	ast_speech_change_state(new_speech, AST_SPEECH_STATE_NOT_READY); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-13 21:03:05 +00:00
										 |  |  | 	/* Pass ourselves to the engine so they can set us up some more and if they error out then do not create a structure */ | 
					
						
							| 
									
										
										
										
											2007-07-11 16:03:31 +00:00
										 |  |  | 	if (engine->create(new_speech, format)) { | 
					
						
							| 
									
										
										
										
											2006-10-13 21:03:05 +00:00
										 |  |  | 		ast_mutex_destroy(&new_speech->lock); | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(new_speech); | 
					
						
							| 
									
										
										
										
											2006-10-13 21:03:05 +00:00
										 |  |  | 		new_speech = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return new_speech; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Destroy a speech structure */ | 
					
						
							|  |  |  | int ast_speech_destroy(struct ast_speech *speech) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Call our engine so we are destroyed properly */ | 
					
						
							|  |  |  | 	speech->engine->destroy(speech); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Deinitialize the lock */ | 
					
						
							|  |  |  | 	ast_mutex_destroy(&speech->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-13 00:18:52 +00:00
										 |  |  | 	/* If results exist on the speech structure, destroy them */ | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	if (speech->results) | 
					
						
							| 
									
										
										
										
											2006-04-13 00:18:52 +00:00
										 |  |  | 		ast_speech_results_free(speech->results); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 	/* If a processing sound is set - free the memory used by it */ | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	if (speech->processing_sound) | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(speech->processing_sound); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Aloha we are done */ | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 	ast_free(speech); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Change state of a speech structure */ | 
					
						
							|  |  |  | int ast_speech_change_state(struct ast_speech *speech, int state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-13 00:18:52 +00:00
										 |  |  | 	switch (state) { | 
					
						
							|  |  |  | 	case AST_SPEECH_STATE_WAIT: | 
					
						
							|  |  |  | 		/* The engine heard audio, so they spoke */ | 
					
						
							|  |  |  | 		ast_set_flag(speech, AST_SPEECH_SPOKE); | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		speech->state = state; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 01:15:50 +00:00
										 |  |  | /*! \brief Change the type of results we want */ | 
					
						
							|  |  |  | int ast_speech_change_results_type(struct ast_speech *speech, enum ast_speech_results_type results_type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	speech->results_type = results_type; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	return (speech->engine->change_results_type ? speech->engine->change_results_type(speech, results_type) : 0); | 
					
						
							| 
									
										
										
										
											2007-04-06 01:15:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | /*! \brief Register a speech recognition engine */ | 
					
						
							|  |  |  | int ast_speech_register(struct ast_speech_engine *engine) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_speech_engine *existing_engine = NULL; | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	/* Confirm the engine meets the minimum API requirements */ | 
					
						
							| 
									
										
										
										
											2007-05-31 18:43:59 +00:00
										 |  |  | 	if (!engine->create || !engine->write || !engine->destroy) { | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Speech recognition engine '%s' did not meet minimum API requirements.\n", engine->name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* If an engine is already loaded with this name, error out */ | 
					
						
							|  |  |  | 	if ((existing_engine = find_engine(engine->name))) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Speech recognition engine '%s' already exists.\n", engine->name); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-26 15:49:18 +00:00
										 |  |  | 	ast_verb(2, "Registered speech recognition engine '%s'\n", engine->name); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Add to the engine linked list and make default if needed */ | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	AST_RWLIST_WRLOCK(&engines); | 
					
						
							|  |  |  | 	AST_RWLIST_INSERT_HEAD(&engines, engine, list); | 
					
						
							|  |  |  | 	if (!default_engine) { | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 		default_engine = engine; | 
					
						
							| 
									
										
										
										
											2007-07-26 15:49:18 +00:00
										 |  |  | 		ast_verb(2, "Made '%s' the default speech recognition engine\n", engine->name); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	AST_RWLIST_UNLOCK(&engines); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \brief Unregister a speech recognition engine */ | 
					
						
							| 
									
										
										
										
											2009-05-21 21:13:09 +00:00
										 |  |  | int ast_speech_unregister(const char *engine_name) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ast_speech_engine *engine = NULL; | 
					
						
							|  |  |  | 	int res = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	if (ast_strlen_zero(engine_name)) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	AST_RWLIST_WRLOCK(&engines); | 
					
						
							|  |  |  | 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&engines, engine, list) { | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 		if (!strcasecmp(engine->name, engine_name)) { | 
					
						
							|  |  |  | 			/* We have our engine... removed it */ | 
					
						
							| 
									
										
										
										
											2007-11-08 05:28:47 +00:00
										 |  |  | 			AST_RWLIST_REMOVE_CURRENT(list); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 			/* If this was the default engine, we need to pick a new one */ | 
					
						
							| 
									
										
										
										
											2010-02-18 23:13:46 +00:00
										 |  |  | 			if (engine == default_engine) { | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 				default_engine = AST_RWLIST_FIRST(&engines); | 
					
						
							| 
									
										
										
										
											2010-02-18 23:13:46 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2007-07-26 15:49:18 +00:00
										 |  |  | 			ast_verb(2, "Unregistered speech recognition engine '%s'\n", engine_name); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 			/* All went well */ | 
					
						
							|  |  |  | 			res = 0; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-11-08 05:28:47 +00:00
										 |  |  | 	AST_RWLIST_TRAVERSE_SAFE_END; | 
					
						
							| 
									
										
										
										
											2007-04-06 01:29:28 +00:00
										 |  |  | 	AST_RWLIST_UNLOCK(&engines); | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int unload_module(void) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* We can not be unloaded */ | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int load_module(void) | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-31 19:24:29 +00:00
										 |  |  | 	return AST_MODULE_LOAD_SUCCESS; | 
					
						
							| 
									
										
										
										
											2006-04-10 23:29:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-20 19:35:02 +00:00
										 |  |  | AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Generic Speech Recognition API", | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 		.load = load_module, | 
					
						
							|  |  |  | 		.unload = unload_module, | 
					
						
							| 
									
										
										
										
											2010-07-20 19:35:02 +00:00
										 |  |  | 		.load_pri = AST_MODPRI_APP_DEPEND, | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 		); |