Merge changes Ie91a9d92,I08af0ef1 into tizen
[platform/core/uifw/stt.git] / common / stt_engine.c
1 /*
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.
12 */
13
14 #include <dlog.h>
15 #include <dlfcn.h>
16 #include <dirent.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <stdbool.h>
20
21 #include "stt_engine.h"
22
23 /*
24 * Internal data structure
25 */
26
27 typedef struct {
28         int     engine_id;
29         char*   engine_path;
30         void    *handle;
31
32         sttpe_funcs_s*  pefuncs;
33         sttpd_funcs_s*  pdfuncs;
34
35         int (*sttp_load_engine)(sttpd_funcs_s* pdfuncs, sttpe_funcs_s* pefuncs);
36         int (*sttp_unload_engine)();
37 } sttengine_s;
38
39 extern const char* stt_tag();
40
41 /** stt engine list */
42 static GSList *g_engine_list;
43
44 static const char* __stt_get_engine_error_code(sttp_error_e err)
45 {
46         switch (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";
56         default:
57                 return "Invalid error code";
58         }
59 }
60
61 static sttengine_s* __get_engine(int engine_id)
62 {
63         /* check whether engine id is valid or not.*/
64         GSList *iter = NULL;
65         sttengine_s *engine = NULL;
66
67         if (g_slist_length(g_engine_list) > 0) {
68                 /*Get a first item*/
69                 iter = g_slist_nth(g_engine_list, 0);
70
71                 while (NULL != iter) {
72                         /*Get handle data from list*/
73                         engine = iter->data;
74
75                         if (engine_id == engine->engine_id) {
76                                 return engine;
77                         }
78
79                         /*Get next item*/
80                         iter = g_slist_next(iter);
81                 }
82         }
83
84         return NULL;
85 }
86
87 /* Register engine id */
88 int stt_engine_load(int engine_id, const char* filepath)
89 {
90         if (NULL == filepath || engine_id < 0) {
91                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
92                 return STTP_ERROR_INVALID_PARAMETER;
93         }
94
95         sttengine_s* engine = NULL;
96         engine = __get_engine(engine_id);
97         if (NULL != engine) {
98                 SECURE_SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] engine id(%d) is already loaded", engine_id);
99                 return 0;
100         }
101
102         SECURE_SLOG(LOG_DEBUG, stt_tag(), "[Engine] Load engine id(%d), path(%s)", engine_id, filepath);
103
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;
109         }
110
111         /* load engine */
112         char *error;
113
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);
117                 free(engine);
118                 return STTP_ERROR_OPERATION_FAILED;
119         }
120
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);
125                 free(engine);
126                 return STTP_ERROR_OUT_OF_MEMORY;
127         }
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);
133                 free(engine);
134                 return STTP_ERROR_OUT_OF_MEMORY;
135         }
136
137         engine->sttp_unload_engine = NULL;
138         engine->sttp_load_engine = NULL;
139
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);
146                 free(engine);
147                 return STTP_ERROR_OPERATION_FAILED;
148         }
149
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);
156                 free(engine);
157                 return STTP_ERROR_OPERATION_FAILED;
158         }
159
160         engine->engine_id = engine_id;
161         engine->engine_path = strdup(filepath);
162
163         engine->pdfuncs->version = 1;
164         engine->pdfuncs->size = sizeof(sttpd_funcs_s);
165
166         int ret = engine->sttp_load_engine(engine->pdfuncs, engine->pefuncs);
167         if (0 != ret) {
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);
173                 free(engine);
174                 return STTP_ERROR_OPERATION_FAILED;
175         }
176
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");
180         }
181
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 ||
197                 */
198         {
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);
204                 free(engine);
205
206                 return STTP_ERROR_OPERATION_FAILED;
207         }
208
209         SECURE_SLOG(LOG_DEBUG, stt_tag(), "[Engine Success] Load engine : version(%d), size(%d)", engine->pefuncs->version, engine->pefuncs->size);
210
211         g_engine_list = g_slist_append(g_engine_list, engine);
212
213         return 0;
214 }
215
216 /* Unregister engine id */
217 int stt_engine_unload(int engine_id)
218 {
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;
224         }
225
226         /* unload engine */
227         engine->sttp_unload_engine();
228         dlclose(engine->handle);
229
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);
233
234         g_engine_list = g_slist_remove(g_engine_list, engine);
235
236         free(engine);
237
238         return 0;
239 }
240
241
242 /* Initialize / Deinitialize */
243 int stt_engine_initialize(int engine_id, sttpe_result_cb result_cb, sttpe_silence_detected_cb silence_cb)
244 {
245         if (NULL == result_cb || NULL == silence_cb) {
246                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
247                 return STTP_ERROR_INVALID_PARAMETER;
248         }
249
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;
255         }
256
257         int ret;
258         ret = engine->pefuncs->initialize(result_cb, silence_cb);
259         if (0 != ret) {
260                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to initialize : %s", __stt_get_engine_error_code(ret));
261                 return STTP_ERROR_OPERATION_FAILED;
262         }
263
264         return 0;
265 }
266
267 int stt_engine_deinitialize(int engine_id)
268 {
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;
274         }
275
276         int ret;
277         ret = engine->pefuncs->deinitialize();
278         if (0 != ret) {
279                 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] Fail to deinitialize : %s", __stt_get_engine_error_code(ret));
280         }
281
282         return 0;
283 }
284
285 static bool __supported_language_cb(const char* language, void* user_data)
286 {
287         GSList** lang_list = (GSList**)user_data;
288
289         if (NULL == language || NULL == lang_list) {
290                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Input parameter is NULL in callback!!!!");
291                 return false;
292         }
293
294         char* temp_lang = g_strdup(language);
295
296         *lang_list = g_slist_append(*lang_list, temp_lang);
297
298         return true;
299 }
300
301 /* Get option */
302 int stt_engine_get_supported_langs(int engine_id, GSList** lang_list)
303 {
304         if (NULL == lang_list) {
305                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
306                 return STTP_ERROR_INVALID_PARAMETER;
307         }
308
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;
314         }
315
316         int ret;
317         ret = engine->pefuncs->foreach_langs(__supported_language_cb, (void*)lang_list);
318         if (0 != ret) {
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;
321         }
322
323         return 0;
324 }
325
326 int stt_engine_is_valid_language(int engine_id, const char* language, bool *is_valid)
327 {
328         if (NULL == language || NULL == is_valid) {
329                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
330                 return STTP_ERROR_INVALID_PARAMETER;
331         }
332
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;
338         }
339
340         bool result;
341         result = engine->pefuncs->is_valid_lang(language);
342
343         *is_valid = result;
344
345         return 0;
346 }
347
348 int stt_engine_get_first_language(int engine_id, char** language)
349 {
350         if (NULL == language) {
351                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
352                 return STTP_ERROR_INVALID_PARAMETER;
353         }
354
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;
360         }
361
362         GSList* lang_list = NULL;
363         int ret;
364         ret = engine->pefuncs->foreach_langs(__supported_language_cb, &lang_list);
365         if (0 != ret) {
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;
368         }
369
370         GSList *iter = NULL;
371         char* data = NULL;
372
373         iter = g_slist_nth(lang_list, 0);
374         if (NULL != iter) {
375                 data = iter->data;
376
377                 if (true == engine->pefuncs->is_valid_lang(data)) {
378                         *language = strdup(data);
379                 } else {
380                         ret = STTP_ERROR_OPERATION_FAILED;
381                 }
382         }
383
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);
388
389                 while (NULL != iter) {
390                         data = iter->data;
391
392                         if (NULL != data)
393                                 free(data);
394
395                         lang_list = g_slist_remove_link(lang_list, iter);
396
397                         iter = g_slist_nth(lang_list, 0);
398                 }
399         }
400
401         return ret;
402 }
403
404 int stt_engine_support_silence(int engine_id, bool* support)
405 {
406         if (NULL == support) {
407                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
408                 return STTP_ERROR_INVALID_PARAMETER;
409         }
410
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;
416         }
417
418         bool result;
419         result = engine->pefuncs->support_silence();
420         *support = result;
421
422         return 0;
423 }
424
425 int stt_engine_support_recognition_type(int engine_id, const char* type, bool* support)
426 {
427         if (NULL == type || NULL == support) {
428                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
429                 return STTP_ERROR_INVALID_PARAMETER;
430         }
431
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;
437         }
438
439         bool result;
440         if (NULL != engine->pefuncs->support_recognition_type) {
441                 result = engine->pefuncs->support_recognition_type(type);
442                 *support = result;
443                 return 0;
444         }
445
446         return STTP_ERROR_OPERATION_FAILED;
447 }
448
449 int stt_engine_get_audio_type(int engine_id, sttp_audio_type_e* types, int* rate, int* channels)
450 {
451         if (NULL == types || NULL == rate || NULL == channels) {
452                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
453                 return STTP_ERROR_INVALID_PARAMETER;
454         }
455
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;
461         }
462
463         int ret;
464         ret = engine->pefuncs->get_audio_format(types, rate, channels);
465         if (0 != ret) {
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;
468         }
469
470         return 0;
471 }
472
473 /* Set option */
474 int stt_engine_set_silence_detection(int engine_id, bool value)
475 {
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;
481         }
482
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;
490         }
491
492         return 0;
493 }
494
495 int stt_engine_check_app_agreed(int engine_id, const char* appid, bool* value)
496 {
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;
502         }
503
504         if (NULL == engine->pefuncs->check_app_agreed) {
505                 SLOG(LOG_WARN, stt_tag(), "[Engine WARNING] Not support app agreement. All app is available");
506                 *value = true;
507                 return 0;
508         }
509
510         int ret = engine->pefuncs->check_app_agreed(appid, value);
511         if (0 != ret) {
512                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to get app agreement : %s", __stt_get_engine_error_code(ret));
513                 *value = false;
514                 return STTP_ERROR_OPERATION_FAILED;
515         }
516
517         return 0;
518 }
519
520 /* Recognition */
521 int stt_engine_recognize_start(int engine_id, const char* lang, const char* recognition_type, void* user_param)
522 {
523         if (NULL == lang || NULL == recognition_type) {
524                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
525                 return STTP_ERROR_INVALID_PARAMETER;
526         }
527
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;
533         }
534
535         int ret = engine->pefuncs->start(lang, recognition_type, user_param);
536         if (0 != ret) {
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;
539         }
540
541         return 0;
542 }
543
544 int stt_engine_set_recording_data(int engine_id, const void* data, unsigned int length)
545 {
546         if (NULL == data) {
547                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Invalid Parameter");
548                 return STTP_ERROR_INVALID_PARAMETER;
549         }
550
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;
556         }
557
558         int ret = engine->pefuncs->set_recording(data, length);
559         if (0 != ret) {
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;
562         }
563
564         return 0;
565 }
566
567 int stt_engine_recognize_stop(int engine_id)
568 {
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;
574         }
575
576         int ret = engine->pefuncs->stop();
577         if (0 != ret) {
578                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to stop : %s", __stt_get_engine_error_code(ret));
579                 return STTP_ERROR_OPERATION_FAILED;
580         }
581
582         return 0;
583 }
584
585 int stt_engine_recognize_cancel(int engine_id)
586 {
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;
592         }
593
594         int ret = engine->pefuncs->cancel();
595         if (0 != ret) {
596                 SLOG(LOG_ERROR, stt_tag(), "[Engine ERROR] Fail to cancel : %s", __stt_get_engine_error_code(ret));
597                 return STTP_ERROR_OPERATION_FAILED;
598         }
599
600         return 0;
601 }
602
603 int stt_engine_foreach_result_time(int engine_id, void* time_info, sttpe_result_time_cb callback, void* user_data)
604 {
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;
610         }
611
612         int ret = engine->pefuncs->foreach_result_time(time_info, callback, user_data);
613         if (0 != ret) {
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;
616         }
617
618         return 0;
619 }
620
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)
623 {
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;
627         }
628
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;
634         }
635
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;
639         }
640
641         int ret = engine->pefuncs->start_file(lang, recognition_type, filepath, audio_type, sample_rate, user_param);
642         if (0 != ret) {
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;
645         }
646
647         return 0;
648 }
649
650 int stt_engine_recognize_cancel_file(int engine_id)
651 {
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;
657         }
658
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;
662         }
663
664         int ret = engine->pefuncs->cancel_file();
665         if (0 != ret) {
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;
668         }
669
670         return 0;
671 }