2 * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd All Rights Reserved
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 * http://www.apache.org/licenses/LICENSE-2.0
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS,
9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and
11 * limitations under the License.
21 #include "stt_engine.h"
24 * Internal data structure
32 sttpe_funcs_s* pefuncs;
33 sttpd_funcs_s* pdfuncs;
35 int (*sttp_load_engine)(sttpd_funcs_s* pdfuncs, sttpe_funcs_s* pefuncs);
36 int (*sttp_unload_engine)();
39 extern const char* stt_tag();
41 /** stt engine list */
42 static GSList *g_engine_list;
44 static const char* __stt_get_engine_error_code(sttp_error_e err)
47 case STTP_ERROR_NONE: return "STTP_ERROR_NONE";
48 case STTP_ERROR_OUT_OF_MEMORY: return "STTP_ERROR_OUT_OF_MEMORY";
49 case STTP_ERROR_IO_ERROR: return "STTP_ERROR_IO_ERROR";
50 case STTP_ERROR_INVALID_PARAMETER: return "STTP_ERROR_INVALID_PARAMETER";
51 case STTP_ERROR_OUT_OF_NETWORK: return "STTP_ERROR_OUT_OF_NETWORK";
52 case STTP_ERROR_INVALID_STATE: return "STTP_ERROR_INVALID_STATE";
53 case STTP_ERROR_INVALID_LANGUAGE: return "STTP_ERROR_INVALID_LANGUAGE";
54 case STTP_ERROR_OPERATION_FAILED: return "STTP_ERROR_OPERATION_FAILED";
55 case STTP_ERROR_NOT_SUPPORTED_FEATURE: return "STTP_ERROR_NOT_SUPPORTED_FEATURE";
57 return "Invalid error code";
61 static sttengine_s* __get_engine(int engine_id)
63 /* check whether engine id is valid or not.*/
65 sttengine_s *engine = NULL;
67 if (g_slist_length(g_engine_list) > 0) {
69 iter = g_slist_nth(g_engine_list, 0);
71 while (NULL != iter) {
72 /*Get handle data from list*/
75 if (engine_id == engine->engine_id) {
80 iter = g_slist_next(iter);
87 /* Register engine id */
88 int stt_engine_load(int engine_id, const char* filepath)
90 if (NULL == filepath || engine_id < 0) {
91 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
92 return STTP_ERROR_INVALID_PARAMETER;
95 sttengine_s* engine = NULL;
96 engine = __get_engine(engine_id);
98 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is already loaded", engine_id);
102 SECURE_SLOG(LOG_DEBUG, stt_tag(), "[Engine] Load engine id(%d), path(%s)", engine_id, filepath);
104 /* allocation memory */
105 engine = (sttengine_s*)calloc(1, sizeof(sttengine_s));
110 engine->handle = dlopen(filepath, RTLD_LAZY);
111 if (!engine->handle) {
112 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine] Invalid engine (Fail dlopen) : %s", filepath);
114 return STTP_ERROR_OPERATION_FAILED;
117 engine->pefuncs = (sttpe_funcs_s*)calloc(1, sizeof(sttpe_funcs_s));
118 engine->pdfuncs = (sttpd_funcs_s*)calloc(1, sizeof(sttpd_funcs_s));
120 engine->sttp_unload_engine = NULL;
121 engine->sttp_load_engine = NULL;
123 engine->sttp_unload_engine = (int (*)())dlsym(engine->handle, "sttp_unload_engine");
124 if (NULL != (error = dlerror()) || NULL == engine->sttp_unload_engine) {
125 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to link daemon to sttp_unload_engine() : %s", error);
126 dlclose(engine->handle);
127 free(engine->pefuncs);
128 free(engine->pdfuncs);
130 return STTP_ERROR_OPERATION_FAILED;
133 engine->sttp_load_engine = (int (*)(sttpd_funcs_s*, sttpe_funcs_s*) )dlsym(engine->handle, "sttp_load_engine");
134 if (NULL != (error = dlerror()) || NULL == engine->sttp_load_engine) {
135 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to link daemon to sttp_load_engine() : %s", error);
136 dlclose(engine->handle);
137 free(engine->pefuncs);
138 free(engine->pdfuncs);
140 return STTP_ERROR_OPERATION_FAILED;
143 engine->engine_id = engine_id;
144 engine->engine_path = strdup(filepath);
146 engine->pdfuncs->version = 1;
147 engine->pdfuncs->size = sizeof(sttpd_funcs_s);
149 int ret = engine->sttp_load_engine(engine->pdfuncs, engine->pefuncs);
151 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail sttp_load_engine() : %s", __stt_get_engine_error_code(ret));
152 dlclose(engine->handle);
153 free(engine->pefuncs);
154 free(engine->pdfuncs);
155 free(engine->engine_path);
157 return STTP_ERROR_OPERATION_FAILED;
160 /* engine error check */
161 if (engine->pefuncs->size != sizeof(sttpe_funcs_s)) {
162 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine is not valid : function size is not matched");
165 if (NULL == engine->pefuncs->initialize ||
166 NULL == engine->pefuncs->deinitialize ||
167 NULL == engine->pefuncs->foreach_langs ||
168 NULL == engine->pefuncs->is_valid_lang ||
169 NULL == engine->pefuncs->support_silence ||
170 NULL == engine->pefuncs->support_recognition_type ||
171 NULL == engine->pefuncs->get_audio_format ||
172 NULL == engine->pefuncs->set_silence_detection ||
173 NULL == engine->pefuncs->start ||
174 NULL == engine->pefuncs->set_recording ||
175 NULL == engine->pefuncs->stop ||
176 NULL == engine->pefuncs->cancel ||
177 NULL == engine->pefuncs->foreach_result_time)
178 /* Current unused functions
179 NULL == engine->pefuncs->start_file_recognition ||
182 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] The engine functions are NOT valid");
183 dlclose(engine->handle);
184 free(engine->pefuncs);
185 free(engine->pdfuncs);
186 free(engine->engine_path);
189 return STTP_ERROR_OPERATION_FAILED;
192 SECURE_SLOG(LOG_DEBUG, stt_tag(), "[Engine Success] Load engine : version(%d), size(%d)",engine->pefuncs->version, engine->pefuncs->size);
194 g_engine_list = g_slist_append(g_engine_list, engine);
199 /* Unregister engine id */
200 int stt_engine_unload(int engine_id)
202 sttengine_s* engine = NULL;
203 engine = __get_engine(engine_id);
204 if (NULL == engine) {
205 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
206 return STTP_ERROR_INVALID_PARAMETER;
210 engine->sttp_unload_engine();
211 dlclose(engine->handle);
213 if (NULL != engine->engine_path) free(engine->engine_path);
214 if (NULL != engine->pefuncs) free(engine->pefuncs);
215 if (NULL != engine->pdfuncs) free(engine->pdfuncs);
217 g_engine_list = g_slist_remove(g_engine_list, engine);
225 /* Initialize / Deinitialize */
226 int stt_engine_initialize(int engine_id, sttpe_result_cb result_cb, sttpe_silence_detected_cb silence_cb)
228 if (NULL == result_cb || NULL == silence_cb) {
229 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
230 return STTP_ERROR_INVALID_PARAMETER;
233 sttengine_s* engine = NULL;
234 engine = __get_engine(engine_id);
235 if (NULL == engine) {
236 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
237 return STTP_ERROR_INVALID_PARAMETER;
241 ret = engine->pefuncs->initialize(result_cb, silence_cb);
243 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to initialize : %s", __stt_get_engine_error_code(ret));
244 return STTP_ERROR_OPERATION_FAILED;
250 int stt_engine_deinitialize(int engine_id)
252 sttengine_s* engine = NULL;
253 engine = __get_engine(engine_id);
254 if (NULL == engine) {
255 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
256 return STTP_ERROR_INVALID_PARAMETER;
260 ret = engine->pefuncs->deinitialize();
262 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] Fail to deinitialize : %s", __stt_get_engine_error_code(ret));
268 static bool __supported_language_cb(const char* language, void* user_data)
270 GSList** lang_list = (GSList**)user_data;
272 if (NULL == language || NULL == lang_list) {
273 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Input parameter is NULL in callback!!!!");
277 char* temp_lang = g_strdup(language);
279 *lang_list = g_slist_append(*lang_list, temp_lang);
285 int stt_engine_get_supported_langs(int engine_id, GSList** lang_list)
287 if (NULL == lang_list) {
288 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
289 return STTP_ERROR_INVALID_PARAMETER;
292 sttengine_s* engine = NULL;
293 engine = __get_engine(engine_id);
294 if (NULL == engine) {
295 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
296 return STTP_ERROR_INVALID_PARAMETER;
300 ret = engine->pefuncs->foreach_langs(__supported_language_cb, (void*)lang_list);
302 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] get language list error : %s", __stt_get_engine_error_code(ret));
303 return STTP_ERROR_OPERATION_FAILED;
309 int stt_engine_is_valid_language(int engine_id, const char* language, bool *is_valid)
311 if (NULL == language || NULL == is_valid) {
312 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
313 return STTP_ERROR_INVALID_PARAMETER;
316 sttengine_s* engine = NULL;
317 engine = __get_engine(engine_id);
318 if (NULL == engine) {
319 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
320 return STTP_ERROR_INVALID_PARAMETER;
324 result = engine->pefuncs->is_valid_lang(language);
331 int stt_engine_get_first_language(int engine_id, char** language)
333 if (NULL == language) {
334 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
335 return STTP_ERROR_INVALID_PARAMETER;
338 sttengine_s* engine = NULL;
339 engine = __get_engine(engine_id);
340 if (NULL == engine) {
341 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
342 return STTP_ERROR_INVALID_PARAMETER;
345 GSList* lang_list = NULL;
347 ret = engine->pefuncs->foreach_langs(__supported_language_cb, &lang_list);
349 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] get language list error : %s", __stt_get_engine_error_code(ret));
350 return STTP_ERROR_OPERATION_FAILED;
356 iter = g_slist_nth(lang_list, 0);
360 if (true == engine->pefuncs->is_valid_lang(data)) {
361 *language = strdup(data);
363 ret = STTP_ERROR_OPERATION_FAILED;
367 /* if list have item */
368 if (g_slist_length(lang_list) > 0) {
369 /* Get a first item */
370 iter = g_slist_nth(lang_list, 0);
372 while (NULL != iter) {
378 lang_list = g_slist_remove_link(lang_list, iter);
380 iter = g_slist_nth(lang_list, 0);
387 int stt_engine_support_silence(int engine_id, bool* support)
389 if (NULL == support) {
390 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
391 return STTP_ERROR_INVALID_PARAMETER;
394 sttengine_s* engine = NULL;
395 engine = __get_engine(engine_id);
396 if (NULL == engine) {
397 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
398 return STTP_ERROR_INVALID_PARAMETER;
402 result = engine->pefuncs->support_silence();
408 int stt_engine_support_recognition_type(int engine_id, const char* type, bool* support)
410 if (NULL == type || NULL == support) {
411 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
412 return STTP_ERROR_INVALID_PARAMETER;
415 sttengine_s* engine = NULL;
416 engine = __get_engine(engine_id);
417 if (NULL == engine) {
418 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
419 return STTP_ERROR_INVALID_PARAMETER;
423 if (NULL != engine->pefuncs->support_recognition_type) {
424 result = engine->pefuncs->support_recognition_type(type);
429 return STTP_ERROR_OPERATION_FAILED;
432 int stt_engine_get_audio_type(int engine_id, sttp_audio_type_e* types, int* rate, int* channels)
434 if (NULL == types || NULL == rate || NULL == channels) {
435 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
436 return STTP_ERROR_INVALID_PARAMETER;
439 sttengine_s* engine = NULL;
440 engine = __get_engine(engine_id);
441 if (NULL == engine) {
442 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
443 return STTP_ERROR_INVALID_PARAMETER;
447 ret = engine->pefuncs->get_audio_format(types, rate, channels);
449 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to get audio format : %s", __stt_get_engine_error_code(ret));
450 return STTP_ERROR_OPERATION_FAILED;
457 int stt_engine_set_silence_detection(int engine_id, bool value)
459 sttengine_s* engine = NULL;
460 engine = __get_engine(engine_id);
461 if (NULL == engine) {
462 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
463 return STTP_ERROR_INVALID_PARAMETER;
466 int ret = engine->pefuncs->set_silence_detection(value);
467 if (STTP_ERROR_NOT_SUPPORTED_FEATURE == ret) {
468 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] Not support silence detection");
469 return STTP_ERROR_NOT_SUPPORTED_FEATURE;
470 } else if (0 != ret) {
471 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to set silence detection : %d", ret);
472 return STTP_ERROR_OPERATION_FAILED;
478 int stt_engine_check_app_agreed(int engine_id, const char* appid, bool* value)
480 sttengine_s* engine = NULL;
481 engine = __get_engine(engine_id);
482 if (NULL == engine) {
483 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
484 return STTP_ERROR_INVALID_PARAMETER;
487 if (NULL == engine->pefuncs->check_app_agreed) {
488 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] Not support app agreement. All app is available");
493 int ret = engine->pefuncs->check_app_agreed(appid, value);
495 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to get app agreement : %s", __stt_get_engine_error_code(ret));
497 return STTP_ERROR_OPERATION_FAILED;
504 int stt_engine_recognize_start(int engine_id, const char* lang, const char* recognition_type, void* user_param)
506 if (NULL == lang || NULL == recognition_type) {
507 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
508 return STTP_ERROR_INVALID_PARAMETER;
511 sttengine_s* engine = NULL;
512 engine = __get_engine(engine_id);
513 if (NULL == engine) {
514 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
515 return STTP_ERROR_INVALID_PARAMETER;
518 int ret = engine->pefuncs->start(lang, recognition_type, user_param);
520 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to start recognition : %s", __stt_get_engine_error_code(ret));
521 return STTP_ERROR_OPERATION_FAILED;
527 int stt_engine_set_recording_data(int engine_id, const void* data, unsigned int length)
530 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
531 return STTP_ERROR_INVALID_PARAMETER;
534 sttengine_s* engine = NULL;
535 engine = __get_engine(engine_id);
536 if (NULL == engine) {
537 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
538 return STTP_ERROR_INVALID_PARAMETER;
541 int ret = engine->pefuncs->set_recording(data, length);
543 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] Fail to set recording : %s", __stt_get_engine_error_code(ret));
544 return STTP_ERROR_OPERATION_FAILED;
550 int stt_engine_recognize_stop(int engine_id)
552 sttengine_s* engine = NULL;
553 engine = __get_engine(engine_id);
554 if (NULL == engine) {
555 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
556 return STTP_ERROR_INVALID_PARAMETER;
559 int ret = engine->pefuncs->stop();
561 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to stop : %s", __stt_get_engine_error_code(ret));
562 return STTP_ERROR_OPERATION_FAILED;
568 int stt_engine_recognize_cancel(int engine_id)
570 sttengine_s* engine = NULL;
571 engine = __get_engine(engine_id);
572 if (NULL == engine) {
573 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
574 return STTP_ERROR_INVALID_PARAMETER;
577 int ret = engine->pefuncs->cancel();
579 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to cancel : %s", __stt_get_engine_error_code(ret));
580 return STTP_ERROR_OPERATION_FAILED;
586 int stt_engine_foreach_result_time(int engine_id, void* time_info, sttpe_result_time_cb callback, void* user_data)
588 sttengine_s* engine = NULL;
589 engine = __get_engine(engine_id);
590 if (NULL == engine) {
591 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
592 return STTP_ERROR_INVALID_PARAMETER;
595 int ret = engine->pefuncs->foreach_result_time(time_info, callback, user_data);
597 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to foreach result time : %s", __stt_get_engine_error_code(ret));
598 return STTP_ERROR_OPERATION_FAILED;
604 int stt_engine_recognize_start_file(int engine_id, const char* lang, const char* recognition_type,
605 const char* filepath, sttp_audio_type_e audio_type, int sample_rate, void* user_param)
607 if (NULL == filepath || NULL == lang || NULL == recognition_type) {
608 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
609 return STTP_ERROR_INVALID_PARAMETER;
612 sttengine_s* engine = NULL;
613 engine = __get_engine(engine_id);
614 if (NULL == engine) {
615 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
616 return STTP_ERROR_INVALID_PARAMETER;
619 if (NULL == engine->pefuncs->start_file) {
620 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine API is invalid");
621 return STTP_ERROR_NOT_SUPPORTED_FEATURE;
624 int ret = engine->pefuncs->start_file(lang, recognition_type, filepath, audio_type, sample_rate, user_param);
626 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to start file recognition : %s", __stt_get_engine_error_code(ret));
627 return STTP_ERROR_OPERATION_FAILED;
633 int stt_engine_recognize_cancel_file(int engine_id)
635 sttengine_s* engine = NULL;
636 engine = __get_engine(engine_id);
637 if (NULL == engine) {
638 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
639 return STTP_ERROR_INVALID_PARAMETER;
642 if (NULL == engine->pefuncs->cancel_file) {
643 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine API is invalid");
644 return STTP_ERROR_NOT_SUPPORTED_FEATURE;
647 int ret = engine->pefuncs->cancel_file();
649 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to start file recognition : %s", __stt_get_engine_error_code(ret));
650 return STTP_ERROR_OPERATION_FAILED;