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));
106 if (NULL == engine) {
107 SLOG(LOG_ERROR, stt_tag(), "[ERROR] Fail to allocate memory");
108 return STTP_ERROR_OUT_OF_MEMORY;
114 engine->handle = dlopen(filepath, RTLD_LAZY);
115 if (!engine->handle) {
116 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine] Invalid engine (Fail dlopen) : %s", filepath);
118 return STTP_ERROR_OPERATION_FAILED;
121 engine->pefuncs = (sttpe_funcs_s*)calloc(1, sizeof(sttpe_funcs_s));
122 if (NULL == engine->pefuncs) {
123 SLOG(LOG_ERROR, stt_tag(), "[ERROR] Fail to allocate memory");
124 dlclose(engine->handle);
126 return STTP_ERROR_OUT_OF_MEMORY;
128 engine->pdfuncs = (sttpd_funcs_s*)calloc(1, sizeof(sttpd_funcs_s));
129 if (NULL == engine->pdfuncs) {
130 SLOG(LOG_ERROR, stt_tag(), "[ERROR] Fail to allocate memory");
131 dlclose(engine->handle);
132 free(engine->pefuncs);
134 return STTP_ERROR_OUT_OF_MEMORY;
137 engine->sttp_unload_engine = NULL;
138 engine->sttp_load_engine = NULL;
140 engine->sttp_unload_engine = (int (*)())dlsym(engine->handle, "sttp_unload_engine");
141 if (NULL != (error = dlerror()) || NULL == engine->sttp_unload_engine) {
142 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to link daemon to sttp_unload_engine() : %s", error);
143 dlclose(engine->handle);
144 free(engine->pefuncs);
145 free(engine->pdfuncs);
147 return STTP_ERROR_OPERATION_FAILED;
150 engine->sttp_load_engine = (int (*)(sttpd_funcs_s*, sttpe_funcs_s*) )dlsym(engine->handle, "sttp_load_engine");
151 if (NULL != (error = dlerror()) || NULL == engine->sttp_load_engine) {
152 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to link daemon to sttp_load_engine() : %s", error);
153 dlclose(engine->handle);
154 free(engine->pefuncs);
155 free(engine->pdfuncs);
157 return STTP_ERROR_OPERATION_FAILED;
160 engine->engine_id = engine_id;
161 engine->engine_path = strdup(filepath);
163 engine->pdfuncs->version = 1;
164 engine->pdfuncs->size = sizeof(sttpd_funcs_s);
166 int ret = engine->sttp_load_engine(engine->pdfuncs, engine->pefuncs);
168 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail sttp_load_engine() : %s", __stt_get_engine_error_code(ret));
169 dlclose(engine->handle);
170 free(engine->pefuncs);
171 free(engine->pdfuncs);
172 free(engine->engine_path);
174 return STTP_ERROR_OPERATION_FAILED;
177 /* engine error check */
178 if (engine->pefuncs->size != sizeof(sttpe_funcs_s)) {
179 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine is not valid : function size is not matched");
182 if (NULL == engine->pefuncs->initialize ||
183 NULL == engine->pefuncs->deinitialize ||
184 NULL == engine->pefuncs->foreach_langs ||
185 NULL == engine->pefuncs->is_valid_lang ||
186 NULL == engine->pefuncs->support_silence ||
187 NULL == engine->pefuncs->support_recognition_type ||
188 NULL == engine->pefuncs->get_audio_format ||
189 NULL == engine->pefuncs->set_silence_detection ||
190 NULL == engine->pefuncs->start ||
191 NULL == engine->pefuncs->set_recording ||
192 NULL == engine->pefuncs->stop ||
193 NULL == engine->pefuncs->cancel ||
194 NULL == engine->pefuncs->foreach_result_time)
195 /* Current unused functions
196 NULL == engine->pefuncs->start_file_recognition ||
199 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] The engine functions are NOT valid");
200 dlclose(engine->handle);
201 free(engine->pefuncs);
202 free(engine->pdfuncs);
203 free(engine->engine_path);
206 return STTP_ERROR_OPERATION_FAILED;
209 SECURE_SLOG(LOG_DEBUG, stt_tag(), "[Engine Success] Load engine : version(%d), size(%d)",engine->pefuncs->version, engine->pefuncs->size);
211 g_engine_list = g_slist_append(g_engine_list, engine);
216 /* Unregister engine id */
217 int stt_engine_unload(int engine_id)
219 sttengine_s* engine = NULL;
220 engine = __get_engine(engine_id);
221 if (NULL == engine) {
222 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
223 return STTP_ERROR_INVALID_PARAMETER;
227 engine->sttp_unload_engine();
228 dlclose(engine->handle);
230 if (NULL != engine->engine_path) free(engine->engine_path);
231 if (NULL != engine->pefuncs) free(engine->pefuncs);
232 if (NULL != engine->pdfuncs) free(engine->pdfuncs);
234 g_engine_list = g_slist_remove(g_engine_list, engine);
242 /* Initialize / Deinitialize */
243 int stt_engine_initialize(int engine_id, sttpe_result_cb result_cb, sttpe_silence_detected_cb silence_cb)
245 if (NULL == result_cb || NULL == silence_cb) {
246 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
247 return STTP_ERROR_INVALID_PARAMETER;
250 sttengine_s* engine = NULL;
251 engine = __get_engine(engine_id);
252 if (NULL == engine) {
253 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
254 return STTP_ERROR_INVALID_PARAMETER;
258 ret = engine->pefuncs->initialize(result_cb, silence_cb);
260 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to initialize : %s", __stt_get_engine_error_code(ret));
261 return STTP_ERROR_OPERATION_FAILED;
267 int stt_engine_deinitialize(int engine_id)
269 sttengine_s* engine = NULL;
270 engine = __get_engine(engine_id);
271 if (NULL == engine) {
272 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
273 return STTP_ERROR_INVALID_PARAMETER;
277 ret = engine->pefuncs->deinitialize();
279 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] Fail to deinitialize : %s", __stt_get_engine_error_code(ret));
285 static bool __supported_language_cb(const char* language, void* user_data)
287 GSList** lang_list = (GSList**)user_data;
289 if (NULL == language || NULL == lang_list) {
290 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Input parameter is NULL in callback!!!!");
294 char* temp_lang = g_strdup(language);
296 *lang_list = g_slist_append(*lang_list, temp_lang);
302 int stt_engine_get_supported_langs(int engine_id, GSList** lang_list)
304 if (NULL == lang_list) {
305 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
306 return STTP_ERROR_INVALID_PARAMETER;
309 sttengine_s* engine = NULL;
310 engine = __get_engine(engine_id);
311 if (NULL == engine) {
312 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
313 return STTP_ERROR_INVALID_PARAMETER;
317 ret = engine->pefuncs->foreach_langs(__supported_language_cb, (void*)lang_list);
319 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] get language list error : %s", __stt_get_engine_error_code(ret));
320 return STTP_ERROR_OPERATION_FAILED;
326 int stt_engine_is_valid_language(int engine_id, const char* language, bool *is_valid)
328 if (NULL == language || NULL == is_valid) {
329 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
330 return STTP_ERROR_INVALID_PARAMETER;
333 sttengine_s* engine = NULL;
334 engine = __get_engine(engine_id);
335 if (NULL == engine) {
336 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
337 return STTP_ERROR_INVALID_PARAMETER;
341 result = engine->pefuncs->is_valid_lang(language);
348 int stt_engine_get_first_language(int engine_id, char** language)
350 if (NULL == language) {
351 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
352 return STTP_ERROR_INVALID_PARAMETER;
355 sttengine_s* engine = NULL;
356 engine = __get_engine(engine_id);
357 if (NULL == engine) {
358 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
359 return STTP_ERROR_INVALID_PARAMETER;
362 GSList* lang_list = NULL;
364 ret = engine->pefuncs->foreach_langs(__supported_language_cb, &lang_list);
366 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] get language list error : %s", __stt_get_engine_error_code(ret));
367 return STTP_ERROR_OPERATION_FAILED;
373 iter = g_slist_nth(lang_list, 0);
377 if (true == engine->pefuncs->is_valid_lang(data)) {
378 *language = strdup(data);
380 ret = STTP_ERROR_OPERATION_FAILED;
384 /* if list have item */
385 if (g_slist_length(lang_list) > 0) {
386 /* Get a first item */
387 iter = g_slist_nth(lang_list, 0);
389 while (NULL != iter) {
395 lang_list = g_slist_remove_link(lang_list, iter);
397 iter = g_slist_nth(lang_list, 0);
404 int stt_engine_support_silence(int engine_id, bool* support)
406 if (NULL == support) {
407 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
408 return STTP_ERROR_INVALID_PARAMETER;
411 sttengine_s* engine = NULL;
412 engine = __get_engine(engine_id);
413 if (NULL == engine) {
414 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
415 return STTP_ERROR_INVALID_PARAMETER;
419 result = engine->pefuncs->support_silence();
425 int stt_engine_support_recognition_type(int engine_id, const char* type, bool* support)
427 if (NULL == type || NULL == support) {
428 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
429 return STTP_ERROR_INVALID_PARAMETER;
432 sttengine_s* engine = NULL;
433 engine = __get_engine(engine_id);
434 if (NULL == engine) {
435 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
436 return STTP_ERROR_INVALID_PARAMETER;
440 if (NULL != engine->pefuncs->support_recognition_type) {
441 result = engine->pefuncs->support_recognition_type(type);
446 return STTP_ERROR_OPERATION_FAILED;
449 int stt_engine_get_audio_type(int engine_id, sttp_audio_type_e* types, int* rate, int* channels)
451 if (NULL == types || NULL == rate || NULL == channels) {
452 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
453 return STTP_ERROR_INVALID_PARAMETER;
456 sttengine_s* engine = NULL;
457 engine = __get_engine(engine_id);
458 if (NULL == engine) {
459 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
460 return STTP_ERROR_INVALID_PARAMETER;
464 ret = engine->pefuncs->get_audio_format(types, rate, channels);
466 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to get audio format : %s", __stt_get_engine_error_code(ret));
467 return STTP_ERROR_OPERATION_FAILED;
474 int stt_engine_set_silence_detection(int engine_id, bool value)
476 sttengine_s* engine = NULL;
477 engine = __get_engine(engine_id);
478 if (NULL == engine) {
479 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
480 return STTP_ERROR_INVALID_PARAMETER;
483 int ret = engine->pefuncs->set_silence_detection(value);
484 if (STTP_ERROR_NOT_SUPPORTED_FEATURE == ret) {
485 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] Not support silence detection");
486 return STTP_ERROR_NOT_SUPPORTED_FEATURE;
487 } else if (0 != ret) {
488 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to set silence detection : %d", ret);
489 return STTP_ERROR_OPERATION_FAILED;
495 int stt_engine_check_app_agreed(int engine_id, const char* appid, bool* value)
497 sttengine_s* engine = NULL;
498 engine = __get_engine(engine_id);
499 if (NULL == engine) {
500 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
501 return STTP_ERROR_INVALID_PARAMETER;
504 if (NULL == engine->pefuncs->check_app_agreed) {
505 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] Not support app agreement. All app is available");
510 int ret = engine->pefuncs->check_app_agreed(appid, value);
512 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to get app agreement : %s", __stt_get_engine_error_code(ret));
514 return STTP_ERROR_OPERATION_FAILED;
521 int stt_engine_recognize_start(int engine_id, const char* lang, const char* recognition_type, void* user_param)
523 if (NULL == lang || NULL == recognition_type) {
524 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
525 return STTP_ERROR_INVALID_PARAMETER;
528 sttengine_s* engine = NULL;
529 engine = __get_engine(engine_id);
530 if (NULL == engine) {
531 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
532 return STTP_ERROR_INVALID_PARAMETER;
535 int ret = engine->pefuncs->start(lang, recognition_type, user_param);
537 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to start recognition : %s", __stt_get_engine_error_code(ret));
538 return STTP_ERROR_OPERATION_FAILED;
544 int stt_engine_set_recording_data(int engine_id, const void* data, unsigned int length)
547 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
548 return STTP_ERROR_INVALID_PARAMETER;
551 sttengine_s* engine = NULL;
552 engine = __get_engine(engine_id);
553 if (NULL == engine) {
554 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
555 return STTP_ERROR_INVALID_PARAMETER;
558 int ret = engine->pefuncs->set_recording(data, length);
560 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] Fail to set recording : %s", __stt_get_engine_error_code(ret));
561 return STTP_ERROR_OPERATION_FAILED;
567 int stt_engine_recognize_stop(int engine_id)
569 sttengine_s* engine = NULL;
570 engine = __get_engine(engine_id);
571 if (NULL == engine) {
572 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
573 return STTP_ERROR_INVALID_PARAMETER;
576 int ret = engine->pefuncs->stop();
578 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to stop : %s", __stt_get_engine_error_code(ret));
579 return STTP_ERROR_OPERATION_FAILED;
585 int stt_engine_recognize_cancel(int engine_id)
587 sttengine_s* engine = NULL;
588 engine = __get_engine(engine_id);
589 if (NULL == engine) {
590 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
591 return STTP_ERROR_INVALID_PARAMETER;
594 int ret = engine->pefuncs->cancel();
596 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to cancel : %s", __stt_get_engine_error_code(ret));
597 return STTP_ERROR_OPERATION_FAILED;
603 int stt_engine_foreach_result_time(int engine_id, void* time_info, sttpe_result_time_cb callback, void* user_data)
605 sttengine_s* engine = NULL;
606 engine = __get_engine(engine_id);
607 if (NULL == engine) {
608 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
609 return STTP_ERROR_INVALID_PARAMETER;
612 int ret = engine->pefuncs->foreach_result_time(time_info, callback, user_data);
614 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to foreach result time : %s", __stt_get_engine_error_code(ret));
615 return STTP_ERROR_OPERATION_FAILED;
621 int stt_engine_recognize_start_file(int engine_id, const char* lang, const char* recognition_type,
622 const char* filepath, sttp_audio_type_e audio_type, int sample_rate, void* user_param)
624 if (NULL == filepath || NULL == lang || NULL == recognition_type) {
625 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
626 return STTP_ERROR_INVALID_PARAMETER;
629 sttengine_s* engine = NULL;
630 engine = __get_engine(engine_id);
631 if (NULL == engine) {
632 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
633 return STTP_ERROR_INVALID_PARAMETER;
636 if (NULL == engine->pefuncs->start_file) {
637 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine API is invalid");
638 return STTP_ERROR_NOT_SUPPORTED_FEATURE;
641 int ret = engine->pefuncs->start_file(lang, recognition_type, filepath, audio_type, sample_rate, user_param);
643 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to start file recognition : %s", __stt_get_engine_error_code(ret));
644 return STTP_ERROR_OPERATION_FAILED;
650 int stt_engine_recognize_cancel_file(int engine_id)
652 sttengine_s* engine = NULL;
653 engine = __get_engine(engine_id);
654 if (NULL == engine) {
655 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is invalid", engine_id);
656 return STTP_ERROR_INVALID_PARAMETER;
659 if (NULL == engine->pefuncs->cancel_file) {
660 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine API is invalid");
661 return STTP_ERROR_NOT_SUPPORTED_FEATURE;
664 int ret = engine->pefuncs->cancel_file();
666 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to start file recognition : %s", __stt_get_engine_error_code(ret));
667 return STTP_ERROR_OPERATION_FAILED;