Merge with Tizen 2.3
[platform/core/uifw/stt.git] / client / stt_file.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 <aul.h>
15 #include <dlfcn.h>
16 #include <dirent.h>
17 #include <dlog.h>
18 #include <Ecore.h>
19 #include <glib.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stdbool.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #include "stt_config_mgr.h"
27 #include "stt_defs.h"
28 #include "stt_engine.h"
29 #include "stt_file.h"
30 #include "stt_file_client.h"
31 #include "stt_network.h"
32
33
34 typedef struct _sttengine_info {
35         int     engine_id;
36
37         char*   engine_uuid;
38         char*   engine_path;
39         char*   engine_name;
40         char*   engine_setting_path;
41         bool    use_network;
42
43         bool    is_loaded;
44 }sttengine_info_s;
45
46 static GSList*  g_engine_list;
47
48 static int      g_engine_id_count = 0;
49
50
51 #define STT_FILE_CONFIG_HANDLE  100000
52
53
54 const char* stt_tag()
55 {
56         return TAG_STTFC;
57 }
58
59 static const char* __stt_file_get_error_code(stt_file_error_e err)
60 {
61         switch(err) {
62         case STT_FILE_ERROR_NONE:                       return "STT_FILE_ERROR_NONE";
63         case STT_FILE_ERROR_OUT_OF_MEMORY:              return "STT_FILE_ERROR_OUT_OF_MEMORY";
64         case STT_FILE_ERROR_IO_ERROR:                   return "STT_FILE_ERROR_IO_ERROR";
65         case STT_FILE_ERROR_INVALID_PARAMETER:          return "STT_FILE_ERROR_INVALID_PARAMETER";
66         case STT_FILE_ERROR_OUT_OF_NETWORK:             return "STT_FILE_ERROR_OUT_OF_NETWORK";
67         case STT_FILE_ERROR_INVALID_STATE:              return "STT_FILE_ERROR_INVALID_STATE";
68         case STT_FILE_ERROR_INVALID_LANGUAGE:           return "STT_FILE_ERROR_INVALID_LANGUAGE";
69         case STT_FILE_ERROR_ENGINE_NOT_FOUND:           return "STT_FILE_ERROR_ENGINE_NOT_FOUND";
70         case STT_FILE_ERROR_OPERATION_FAILED:           return "STT_FILE_ERROR_OPERATION_FAILED";
71         case STT_FILE_ERROR_NOT_SUPPORTED_FEATURE:      return "STT_FILE_ERROR_NOT_SUPPORTED_FEATURE";
72         case STT_FILE_ERROR_NOT_AGREE_SERVICE:          return "STT_FILE_ERROR_NOT_AGREE_SERVICE";
73         default:
74                 return "Invalid error code";
75         }
76 }
77
78 void __stt_file_engine_info_cb(const char* engine_uuid, const char* engine_name, const char* setting_ug_name, 
79                       bool use_network, void* user_data)
80 {
81         sttengine_info_s* temp = (sttengine_info_s*)user_data; 
82
83         temp->engine_uuid = g_strdup(engine_uuid);
84         temp->engine_name = g_strdup(engine_name);
85         temp->engine_setting_path = g_strdup(setting_ug_name);
86         temp->use_network = use_network;
87 }
88
89 static int __stt_file_get_engine_info(const char* filepath, sttengine_info_s** info)
90 {
91         if (NULL == filepath || NULL == info) {
92                 SLOG(LOG_ERROR, TAG_STTFC, "[Engine Agent ERROR] Invalid Parameter"); 
93                 return STT_FILE_ERROR_INVALID_PARAMETER;
94         }
95
96         /* load engine */
97         char *error;
98         void* handle;
99
100         handle = dlopen (filepath, RTLD_LAZY);
101
102         if (!handle) {
103                 SECURE_SLOG(LOG_WARN, TAG_STTFC, "[Engine Agent] Invalid engine : %s", filepath); 
104                 return -1;
105         }
106
107         /* link engine to daemon */
108         dlsym(handle, "sttp_load_engine");
109         if ((error = dlerror()) != NULL) {
110                 SLOG(LOG_WARN, TAG_STTFC, "[Engine Agent] Invalid engine. Fail to open sttp_load_engine : %s", error); 
111                 dlclose(handle);
112                 return -1;
113         }
114
115         dlsym(handle, "sttp_unload_engine");
116         if ((error = dlerror()) != NULL) {
117                 SLOG(LOG_WARN, TAG_STTFC, "[Engine Agent] Invalid engine. Fail to open sttp_unload_engine : %s", error); 
118                 dlclose(handle);
119                 return -1;
120         }
121
122         int (*get_engine_info)(sttpe_engine_info_cb callback, void* user_data);
123
124         get_engine_info = (int (*)(sttpe_engine_info_cb, void*))dlsym(handle, "sttp_get_engine_info");
125         if ((error = dlerror()) != NULL || NULL == get_engine_info) {
126                 SLOG(LOG_WARN, TAG_STTFC, "[Engine Agent WARNING] Invalid engine. Fail to open sttp_get_engine_info : %s", error); 
127                 dlclose(handle);
128                 return -1;
129         }
130
131         sttengine_info_s* temp;
132         temp = (sttengine_info_s*)calloc(1, sizeof(sttengine_info_s));
133
134         /* get engine info */
135         if (0 != get_engine_info(__stt_file_engine_info_cb, (void*)temp)) {
136                 SLOG(LOG_ERROR, TAG_STTFC, "[Engine Agent ERROR] Fail to get engine info from engine"); 
137                 dlclose(handle);
138                 free(temp);
139                 return -1;
140         }
141
142         /* close engine */
143         dlclose(handle);
144
145         temp->engine_id = g_engine_id_count;
146         g_engine_id_count++;
147
148         temp->engine_path = g_strdup(filepath);
149         temp->is_loaded = false;
150
151         SLOG(LOG_DEBUG, TAG_STTFC, "----- Valid Engine");
152         SECURE_SLOG(LOG_DEBUG, TAG_STTFC, "Engine id : %d", temp->engine_id);
153         SECURE_SLOG(LOG_DEBUG, TAG_STTFC, "Engine uuid : %s", temp->engine_uuid);
154         SECURE_SLOG(LOG_DEBUG, TAG_STTFC, "Engine name : %s", temp->engine_name);
155         SECURE_SLOG(LOG_DEBUG, TAG_STTFC, "Engine path : %s", temp->engine_path);
156         SECURE_SLOG(LOG_DEBUG, TAG_STTFC, "Engine setting path : %s", temp->engine_setting_path);
157         SECURE_SLOG(LOG_DEBUG, TAG_STTFC, "Use network : %s", temp->use_network ? "true":"false");
158         SLOG(LOG_DEBUG, TAG_STTFC, "-----");
159         SLOG(LOG_DEBUG, TAG_STTFC, "  ");
160
161         *info = temp;
162
163         return 0;
164 }
165
166 static bool __stt_file_is_engine(const char* filepath)
167 {
168         GSList *iter = NULL;
169         sttengine_info_s *engine = NULL;
170
171         if (0 < g_slist_length(g_engine_list)) {
172                 /* Get a first item */
173                 iter = g_slist_nth(g_engine_list, 0);
174
175                 while (NULL != iter) {
176                         /* Get handle data from list */
177                         engine = iter->data;
178
179                         if (0 == strcmp(engine->engine_path, filepath)) {
180                                 return true;
181                         }
182                 
183                         iter = g_slist_next(iter);
184                 }
185         }
186
187         return false;
188 }
189
190 void __stt_file_relseae_engine_info()
191 {
192         GSList *iter = NULL;
193
194         /* Release engine list */
195         sttengine_info_s *engine = NULL;
196
197         if (0 < g_slist_length(g_engine_list)) {
198                 /* Get a first item */
199                 iter = g_slist_nth(g_engine_list, 0);
200
201                 while (NULL != iter) {
202                         /* Get handle data from list */
203                         engine = iter->data;
204                         g_engine_list = g_slist_remove_link(g_engine_list, iter);
205                         
206                         /* Check engine unload */
207                         if (NULL != engine) {
208                                 if (engine->is_loaded) {
209                                         SECURE_SLOG(LOG_DEBUG, TAG_STTFC, "[Engine Agent] Unload engine id(%d)", engine->engine_id);
210
211                                         if (0 != stt_engine_deinitialize(engine->engine_id)) 
212                                                 SECURE_SLOG(LOG_WARN, TAG_STTFC, "[Engine Agent] Fail to deinitialize engine id(%d)", engine->engine_id);
213
214                                         if (0 != stt_engine_unload(engine->engine_id))
215                                                 SECURE_SLOG(LOG_WARN, TAG_STTFC, "[Engine Agent] Fail to unload engine id(%d)", engine->engine_id);
216
217                                         engine->is_loaded = false;
218                                 }
219
220                                 if (NULL != engine->engine_uuid)        free(engine->engine_uuid);
221                                 if (NULL != engine->engine_path)        free(engine->engine_path);
222                                 if (NULL != engine->engine_name)        free(engine->engine_name);
223                                 if (NULL != engine->engine_setting_path)free(engine->engine_setting_path);
224
225                                 free(engine);
226                         }
227
228                         iter = g_slist_nth(g_engine_list, 0);
229                 }
230         }
231 }
232
233 static sttengine_info_s* __stt_file_get_engine_by_id(int engine_id)
234 {
235         GSList *iter = NULL;
236         sttengine_info_s *data = NULL;
237
238         iter = g_slist_nth(g_engine_list, 0);
239
240         while (NULL != iter) {
241
242                 data = iter->data;
243
244                 if (data->engine_id == engine_id) 
245                         return data;
246
247                 iter = g_slist_next(iter);
248         }
249
250         return NULL;
251 }
252
253 void __stt_file_result_cb(sttp_result_event_e event, const char* type, const char** data, int data_count, 
254                  const char* msg, void* time_info, void *user_data)
255 {
256         
257         SLOG(LOG_DEBUG, TAG_STTFC, "[STT FILE] Result event(%d) type(%s) msg(%s)", event, type, msg);
258
259         if (NULL != data) {
260                 int i = 0;
261                 for (i = 0;i < data_count;i++) {
262                         if (NULL != data[i]) {
263                                 SLOG(LOG_DEBUG, TAG_STTFC, "[STT FILE] [%d] %s", i, data[i]);
264                         }
265                 }
266         }
267
268         stt_file_client_s* client = stt_file_client_get();
269
270         /* check handle */
271         if (NULL == client) {
272                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Fail to notify error : A handle is not valid");
273                 return;
274         }
275
276         if (NULL != time_info) {
277                 client->time_info = time_info;
278         }
279
280         if (NULL != client->recognition_result_cb) {
281                 stt_file_client_use_callback(client);
282                 client->recognition_result_cb(event, data, data_count, msg, client->recognition_result_user_data);
283                 stt_file_client_not_use_callback(client);
284                 SLOG(LOG_DEBUG, TAG_STTFC, "client recognition result callback called");
285         } else {
286                 SLOG(LOG_WARN, TAG_STTFC, "[WARNING] User recognition result callback is NULL");
287         }
288
289         client->time_info = NULL;
290
291         if (STTP_RESULT_EVENT_FINAL_RESULT == event || STTP_RESULT_EVENT_ERROR == event) {
292                 SLOG(LOG_DEBUG, TAG_STTFC, "[STT FILE] State change : 'Ready'");
293                 
294                 client->before_state = client->current_state;
295                 client->current_state = STT_FILE_STATE_READY;
296
297                 if (NULL != client->state_changed_cb) {
298                         stt_file_client_use_callback(client);
299                         client->state_changed_cb(client->before_state, client->current_state, client->state_changed_user_data); 
300                         stt_file_client_not_use_callback(client);
301                         SLOG(LOG_DEBUG, TAG_STTFC, "State changed callback is called");
302                 } else {
303                         SLOG(LOG_WARN, TAG_STTFC, "[WARNING] State changed callback is null");
304                 }
305         }
306
307         return;
308 }
309
310 void __stt_file_silence_cb(sttp_silence_type_e type, void *user_data)
311 {
312         SLOG(LOG_WARN, TAG_STTFC, "[WARNING] This callback should NOT be called.");
313         return;
314 }
315
316 static int __stt_file_load_engine(sttengine_info_s* engine)
317 {
318         if (NULL == engine) {
319                 SLOG(LOG_ERROR, TAG_STTFC, "[STT FILE ERROR] Input engine is NULL");
320                 return STT_FILE_ERROR_INVALID_PARAMETER;
321         }
322
323         if (0 != stt_engine_load(engine->engine_id, engine->engine_path)) {
324                 SLOG(LOG_ERROR, TAG_STTFC, "[STT FILE ERROR] Fail to load engine(%s)", engine->engine_path);
325                 return STT_FILE_ERROR_OPERATION_FAILED;
326         }
327
328         int ret = stt_engine_initialize(engine->engine_id, __stt_file_result_cb, __stt_file_silence_cb);
329         if (0 != ret) {
330                 SECURE_SLOG(LOG_ERROR, TAG_STTFC, "[Engine Agent ERROR] Fail to initialize engine : id(%d) path(%s)", engine->engine_id, engine->engine_path);
331                 return STT_FILE_ERROR_OPERATION_FAILED;
332         }
333
334         engine->is_loaded = true;
335
336         SECURE_SLOG(LOG_DEBUG, TAG_STTFC, "[STT FILE Success] Load engine id(%d) path(%s)", engine->engine_id, engine->engine_path);
337
338         return STT_FILE_ERROR_NONE;
339 }
340
341 int stt_file_initialize()
342 {
343         SLOG(LOG_DEBUG, TAG_STTFC, "===== Initialize STT FILE");
344
345         stt_file_client_s* client = stt_file_client_get();
346         if (NULL != client) {
347                 SLOG(LOG_ERROR, TAG_STTFC, "[STT FILE ERROR] Already initialized");
348                 return STT_FILE_ERROR_INVALID_STATE;
349         }
350
351         /* Get file name from default engine directory */
352         DIR *dp = NULL;
353         int ret = -1;
354         struct dirent entry;
355         struct dirent *dirp = NULL;
356         dp  = opendir(STT_DEFAULT_ENGINE);
357         if (NULL != dp) {
358                 do {
359                         ret = readdir_r(dp, &entry, &dirp);
360                         if (0 != ret) {
361                                 SLOG(LOG_ERROR, TAG_STTFC, "[File ERROR] Fail to read directory");
362                                 break;
363                         }
364
365                         if (NULL != dirp) {
366                                 sttengine_info_s* info;
367                                 char* filepath;
368                                 int filesize;
369
370                                 filesize = strlen(STT_DEFAULT_ENGINE) + strlen(dirp->d_name) + 5;
371                                 filepath = (char*)calloc(filesize, sizeof(char));
372
373
374                                 if (NULL != filepath) {
375                                         snprintf(filepath, filesize, "%s/%s", STT_DEFAULT_ENGINE, dirp->d_name);
376                                 } else {
377                                         SLOG(LOG_ERROR, TAG_STTFC, "[Engine Agent ERROR] Memory not enough!!");
378                                         continue;
379                                 }
380
381                                 if (false == __stt_file_is_engine(filepath)) {
382                                         /* get its and update engine list */
383                                         if (0 == __stt_file_get_engine_info(filepath, &info)) {
384                                                 /* add engine info to g_engine_list */
385                                                 g_engine_list = g_slist_append(g_engine_list, info);
386                                         }
387                                 }
388
389                                 if (NULL != filepath)
390                                         free(filepath);
391                         }
392                 } while (NULL != dirp);
393
394                 closedir(dp);
395         } else {
396                 SLOG(LOG_WARN, TAG_STTFC, "[Engine Agent WARNING] Fail to open default directory"); 
397         }
398
399         if (0 >= g_slist_length(g_engine_list)) {
400                 SLOG(LOG_WARN, TAG_STTFC, "[STT FILE WARNING] Not found engine");
401                 return STT_FILE_ERROR_ENGINE_NOT_FOUND;
402         }
403
404         ret = stt_file_client_new();
405         if (0 != ret) {
406                 SLOG(LOG_ERROR, TAG_STTFC, "[STT FILE ERROR] Fail to create client : %s", __stt_file_get_error_code(ret));
407                 return STT_FILE_ERROR_OPERATION_FAILED;
408         }
409
410         client = stt_file_client_get();
411         if (NULL == client) {
412                 SLOG(LOG_ERROR, TAG_STTFC, "[STT FILE ERROR] Not initialized");
413                 return STT_FILE_ERROR_OPERATION_FAILED;
414         }
415
416         ret = stt_config_mgr_initialize(getpid() + STT_FILE_CONFIG_HANDLE);
417         if (0 != ret) {
418                 SLOG(LOG_ERROR, TAG_STTFC, "[STT FILE ERROR] Fail to init config manager : %s", __stt_file_get_error_code(ret));
419                 stt_file_client_destroy();
420                 return STT_FILE_ERROR_OPERATION_FAILED;
421         }
422
423         /* Get engine */
424         char* engine_id = NULL;
425         ret = stt_config_mgr_get_engine(&engine_id);
426         if (0 != ret) {
427                 SLOG(LOG_ERROR, TAG_STTFC, "[STT FILE ERROR] Fail to get engine id : %s", __stt_file_get_error_code(ret));
428                 stt_file_client_destroy();
429                 stt_config_mgr_finalize(getpid() + STT_FILE_CONFIG_HANDLE);
430                 __stt_file_relseae_engine_info();
431                 return STT_FILE_ERROR_OPERATION_FAILED;
432         }
433         
434         SLOG(LOG_DEBUG, TAG_STTFC, "[STT FILE] Get engine id : %s", engine_id);
435
436         bool is_found = false;
437
438         sttengine_info_s* engine = NULL;
439         GSList *iter = NULL;
440         /* load engine */
441         if (0 < g_slist_length(g_engine_list)) {
442                 /* Get a first item */
443                 iter = g_slist_nth(g_engine_list, 0);
444
445                 while (NULL != iter) {
446                         /* Get handle data from list */
447                         engine = iter->data;
448
449                         if (0 == strcmp(engine->engine_uuid, engine_id)) {
450                                 is_found = true;
451                                 break;
452                         }
453
454                         iter = g_slist_next(iter);
455                 }
456         }
457
458         if (NULL != engine_id)  free(engine_id);
459
460         if (false == is_found) {
461                 SLOG(LOG_WARN, TAG_STTFC, "[STT FILE WARNING] Fail to find default engine");
462                 iter = g_slist_nth(g_engine_list, 0);
463                 engine = iter->data;
464
465                 if (NULL == engine) {
466                         SLOG(LOG_ERROR, TAG_STTFC, "[Engine Agent ERROR] Fail to initialize engine");
467                         stt_file_client_destroy();
468                         stt_config_mgr_finalize(getpid() + STT_FILE_CONFIG_HANDLE);
469                         __stt_file_relseae_engine_info();
470                         return STT_FILE_ERROR_OPERATION_FAILED;
471                 }
472                 SLOG(LOG_WARN, TAG_STTFC, "[STT FILE WARNING] Set default engine (%s)", engine->engine_name);
473         }
474
475         ret = __stt_file_load_engine(engine);
476         if (0 != ret) {
477                 SLOG(LOG_ERROR, TAG_STTFC, "[Engine Agent ERROR] Fail to initialize engine");
478                 stt_file_client_destroy();
479                 stt_config_mgr_finalize(getpid() + STT_FILE_CONFIG_HANDLE);
480                 __stt_file_relseae_engine_info();
481                 return STT_FILE_ERROR_OPERATION_FAILED;
482         }
483
484         client->current_engine_id = engine->engine_id;
485
486         stt_network_initialize();
487
488         SECURE_SLOG(LOG_DEBUG, TAG_STTFC, "[STT FILE Success] Initialize : pid(%d)", getpid());
489
490         SLOG(LOG_DEBUG, TAG_STTFC, "=====");
491         SLOG(LOG_DEBUG, TAG_STTFC, " ");
492
493         return STT_FILE_ERROR_NONE;
494 }
495
496 int stt_file_deinitialize()
497 {
498         SLOG(LOG_DEBUG, TAG_STTFC, "===== Deinitialize STT FILE");
499         
500         stt_file_client_s* client = stt_file_client_get();
501         if (NULL == client) {
502                 SLOG(LOG_ERROR, TAG_STTFC, "[STT FILE ERROR] Not initialized");
503                 return STT_FILE_ERROR_INVALID_STATE;
504         }
505
506         /* check used callback */
507         if (0 != stt_file_client_get_use_callback(client)) {
508                 SLOG(LOG_ERROR, TAG_STTFC, "[STT FILE ERROR] Client should NOT deinitialize STT FILE in callback function");
509                 return STT_FILE_ERROR_OPERATION_FAILED;
510         }
511
512         stt_network_finalize();
513
514         stt_config_mgr_finalize(getpid() + STT_FILE_CONFIG_HANDLE);
515
516         /* check state */
517         switch (client->current_state) {
518         case STT_FILE_STATE_PROCESSING:
519                 /* Cancel file recognition */
520                 stt_engine_recognize_cancel_file(client->current_engine_id);
521
522         case STT_FILE_STATE_READY:
523                 /* Unload engine */
524                 __stt_file_relseae_engine_info();
525
526                 /* Free resources */
527                 stt_file_client_destroy();
528                 break;
529
530         case STT_FILE_STATE_NONE:
531                 SLOG(LOG_WARN, TAG_STTFC, "[STT FILE WARNING] NOT initialized");
532                 return 0;
533         default:
534                 break;
535         }
536
537         SLOG(LOG_DEBUG, TAG_STTFC, "=====");
538         SLOG(LOG_DEBUG, TAG_STTFC, " ");
539
540         return STT_FILE_ERROR_NONE;
541 }
542
543 int stt_file_get_state(stt_file_state_e* state)
544 {
545         if (NULL == state) {
546                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Input parameter is NULL");
547                 return STT_FILE_ERROR_INVALID_PARAMETER;
548         }
549
550         stt_file_client_s* client = stt_file_client_get();
551
552         if (NULL == client) {
553                 SLOG(LOG_DEBUG, TAG_STTFC, "[STT FILE] Not initialized");
554                 *state = STT_FILE_STATE_NONE;
555                 return STT_FILE_ERROR_NONE;
556         }
557
558         *state = client->current_state;
559
560         switch(*state) {
561                 case STT_FILE_STATE_NONE:       SLOG(LOG_DEBUG, TAG_STTFC, "Current state is 'NONE'");          break;
562                 case STT_FILE_STATE_READY:      SLOG(LOG_DEBUG, TAG_STTFC, "Current state is 'Ready'");         break;
563                 case STT_FILE_STATE_PROCESSING: SLOG(LOG_DEBUG, TAG_STTFC, "Current state is 'Processing'");    break;
564                 default:                        SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Invalid value");            break;
565         }
566
567         return STT_FILE_ERROR_NONE;
568 }
569
570 int stt_file_foreach_supported_engines(stt_file_supported_engine_cb callback, void* user_data)
571 {
572         SLOG(LOG_DEBUG, TAG_STTFC, "===== Foreach Supported engine");
573
574         if (NULL == callback) {
575                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Input parameter is NULL");
576                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
577                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
578                 return STT_FILE_ERROR_INVALID_PARAMETER;
579         }
580
581         stt_file_client_s* client = stt_file_client_get();
582
583         /* check handle */
584         if (NULL == client) {
585                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] A handle is not available");
586                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
587                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
588                 return STT_FILE_ERROR_INVALID_PARAMETER;
589         }
590
591         if (client->current_state != STT_FILE_STATE_READY) {
592                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Invalid State: Current state is not 'Ready'");
593                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
594                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
595                 return STT_FILE_ERROR_INVALID_STATE;
596         }
597
598         GSList *iter = NULL;
599         sttengine_info_s *engine = NULL;
600
601         /* Get a first item */
602         iter = g_slist_nth(g_engine_list, 0);
603
604         while (NULL != iter) {
605                 /* Get handle data from list */
606                 engine = iter->data;
607
608                 if (NULL != engine) {
609                         if (false == callback(engine->engine_uuid, engine->engine_name, user_data)) {
610                                 break;
611                         }
612                 }
613                 iter = g_slist_next(iter);
614         }
615
616         SLOG(LOG_DEBUG, TAG_STTFC, "=====");
617         SLOG(LOG_DEBUG, TAG_STTFC, " ");
618         
619         return STT_FILE_ERROR_NONE;
620 }
621
622 int stt_file_get_engine(char** engine_id)
623 {
624         SLOG(LOG_DEBUG, TAG_STTFC, "===== Get current engine");
625
626         if (NULL == engine_id) {
627                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Input parameter is NULL");
628                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
629                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
630                 return STT_FILE_ERROR_INVALID_PARAMETER;
631         }
632
633         stt_file_client_s* client = stt_file_client_get();
634
635         /* check handle */
636         if (NULL == client) {
637                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] A handle is not available");
638                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
639                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
640                 return STT_FILE_ERROR_INVALID_PARAMETER;
641         }
642
643         if (client->current_state != STT_FILE_STATE_READY) {
644                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Invalid State: Current state is not 'Ready'");
645                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
646                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
647                 return STT_FILE_ERROR_INVALID_STATE;
648         }
649
650         sttengine_info_s* engine = NULL;
651         engine = __stt_file_get_engine_by_id(client->current_engine_id);
652         if (NULL == engine) {
653                 SECURE_SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Fail to get engine info(%d)", client->current_engine_id);
654                 return STT_FILE_ERROR_OPERATION_FAILED;
655         }
656
657         *engine_id = strdup(engine->engine_uuid);
658
659         SLOG(LOG_DEBUG, TAG_STTFC, "=====");
660         SLOG(LOG_DEBUG, TAG_STTFC, " ");
661
662         return STT_FILE_ERROR_NONE;
663 }
664
665 int stt_file_set_engine(const char* engine_id)
666 {       
667         SLOG(LOG_DEBUG, TAG_STTFC, "===== Set current engine");
668
669         if (NULL == engine_id) {
670                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Input parameter is NULL");
671                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
672                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
673                 return STT_FILE_ERROR_INVALID_PARAMETER;
674         }
675
676         stt_file_client_s* client = stt_file_client_get();
677
678         /* check handle */
679         if (NULL == client) {
680                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] A handle is not available");
681                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
682                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
683                 return STT_FILE_ERROR_INVALID_PARAMETER;
684         }
685
686         /* check state */
687         if (client->current_state != STT_FILE_STATE_READY) {
688                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Invalid State: Current state is not 'Ready'");
689                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
690                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
691                 return STT_FILE_ERROR_INVALID_STATE;
692         }
693
694         GSList *iter = NULL;
695         sttengine_info_s *engine = NULL;
696
697         int temp_old_engine = -1;
698
699         /* Get a first item */
700         iter = g_slist_nth(g_engine_list, 0);
701
702         while (NULL != iter) {
703                 /* Get handle data from list */
704                 engine = iter->data;
705
706                 if (0 == strcmp(engine->engine_uuid, engine_id)) {
707                         if (client->current_engine_id != engine->engine_id) {
708                                 temp_old_engine = client->current_engine_id;
709                         } else {
710                                 SLOG(LOG_DEBUG, TAG_STTFC, "Already loaded engine : %s", engine_id);
711                                 return 0;
712                         }
713
714                         break;
715                 }
716         
717                 iter = g_slist_next(iter);
718                 engine = NULL;
719         }
720         
721         if (NULL == engine) {
722                 SLOG(LOG_ERROR, TAG_STTFC, "[Engine Agent ERROR] Engine id is NOT valid");
723                 return STT_FILE_ERROR_INVALID_PARAMETER;
724         }
725
726         int ret = __stt_file_load_engine(engine);
727         if (0 != ret) {
728                 SLOG(LOG_ERROR, TAG_STTFC, "[Engine Agent ERROR] Fail to initialize engine");
729                 return STT_FILE_ERROR_OPERATION_FAILED;
730         }
731
732         client->current_engine_id = engine->engine_id;
733
734         if (-1 != temp_old_engine) {
735                 stt_engine_deinitialize(temp_old_engine);
736                 stt_engine_unload(temp_old_engine);
737         }
738
739         SLOG(LOG_DEBUG, TAG_STTFC, "=====");
740         SLOG(LOG_DEBUG, TAG_STTFC, " ");
741
742         return 0;
743 }
744
745 bool __stt_config_supported_language_cb(const char* engine_id, const char* language, void* user_data)
746 {
747         stt_file_client_s* client = stt_file_client_get();
748         if (NULL == client) {
749                 SLOG(LOG_ERROR, TAG_STTFC, "[WARNING] A handle is not valid");
750                 return false;
751         }
752
753         /* call callback function */
754         if (NULL != client->supported_lang_cb) {
755                 return client->supported_lang_cb(language, client->supported_lang_user_data);
756         } else {
757                 SLOG(LOG_WARN, TAG_STTFC, "No registered callback function of supported languages");
758         }
759
760         return false;
761 }
762
763 int stt_file_foreach_supported_languages(stt_file_supported_language_cb callback, void* user_data)
764 {
765         SLOG(LOG_DEBUG, TAG_STTFC, "===== Foreach Supported Language");
766
767         if (NULL == callback) {
768                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Input parameter is NULL");
769                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
770                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
771                 return STT_FILE_ERROR_INVALID_PARAMETER;
772         }
773
774         stt_file_client_s* client = stt_file_client_get();
775
776         /* check handle */
777         if (NULL == client) {
778                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] A handle is not available");
779                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
780                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
781                 return STT_FILE_ERROR_INVALID_PARAMETER;
782         }
783
784         sttengine_info_s* engine = NULL;
785         engine = __stt_file_get_engine_by_id(client->current_engine_id);
786         if (NULL == engine) {
787                 SECURE_SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Fail to get engine info(%d)", client->current_engine_id);
788                 return STT_FILE_ERROR_OPERATION_FAILED;
789         }
790
791         client->supported_lang_cb = callback;
792         client->supported_lang_user_data = user_data;
793
794         int ret = -1;
795         ret = stt_config_mgr_get_language_list(engine->engine_uuid, __stt_config_supported_language_cb, NULL);
796         if (0 != ret) {
797                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Fail to get languages");
798         }
799
800         client->supported_lang_cb = NULL;
801         client->supported_lang_user_data = NULL;
802
803         SLOG(LOG_DEBUG, TAG_STTFC, "=====");
804         SLOG(LOG_DEBUG, TAG_STTFC, " ");
805
806         return STT_FILE_ERROR_NONE;
807 }
808
809 int stt_file_start(const char* language, const char* type, const char* filepath, 
810                 stt_file_audio_type_e audio_type, int sample_rate)
811 {
812         SLOG(LOG_DEBUG, TAG_STTFC, "===== STT FILE START");
813
814         stt_file_client_s* client = stt_file_client_get();
815
816         /* check handle */
817         if (NULL == client) {
818                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] A handle is not available");
819                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
820                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
821                 return STT_FILE_ERROR_INVALID_STATE;
822         }
823
824         /* check state */
825         if (client->current_state != STT_FILE_STATE_READY) {
826                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Invalid State: Current state is not READY");
827                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
828                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
829                 return STT_FILE_ERROR_INVALID_STATE;
830         }
831
832         if (NULL == language || NULL == filepath) {
833                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Input parameter is NULL");
834                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
835                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
836                 return STT_FILE_ERROR_INVALID_PARAMETER;
837         }
838
839         /* check if engine use network */
840         sttengine_info_s* engine = NULL;
841         engine = __stt_file_get_engine_by_id(client->current_engine_id);
842         if (NULL == engine) {
843                 SECURE_SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Fail to get engine info(%d)", client->current_engine_id);
844                 return STT_FILE_ERROR_OPERATION_FAILED;
845         }
846
847         if (true == engine->use_network) {
848                 if (false == stt_network_is_connected()) {
849                         SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Disconnect network. Current engine needs to network connection.");
850                         return STT_FILE_ERROR_OUT_OF_NETWORK;
851                 }
852         }
853
854         SLOG(LOG_DEBUG, TAG_STTFC, "[START Info] Engine(%d) Lang(%s) Type(%s) Filepath(%s) Audio(%d) Sample rate(%d)"
855                 ,client->current_engine_id, language, type, filepath, audio_type, sample_rate);
856
857         int ret = -1;
858         ret = stt_engine_recognize_start_file(client->current_engine_id, language, type, filepath, audio_type, sample_rate, NULL);
859         if (0 != ret) {
860                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Fail to start file recognition");
861                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
862                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
863                 return STT_FILE_ERROR_OPERATION_FAILED;
864         }
865
866         client->before_state = client->current_state;
867         client->current_state = STT_FILE_STATE_PROCESSING;
868
869         if (NULL != client->state_changed_cb) {
870                 stt_file_client_use_callback(client);
871                 client->state_changed_cb(client->before_state, client->current_state, client->state_changed_user_data); 
872                 stt_file_client_not_use_callback(client);
873                 SLOG(LOG_DEBUG, TAG_STTFC, "State changed callback is called");
874         } else {
875                 SLOG(LOG_WARN, TAG_STTFC, "[WARNING] State changed callback is null");
876         }
877
878         SLOG(LOG_DEBUG, TAG_STTFC, "=====");
879         SLOG(LOG_DEBUG, TAG_STTFC, " ");
880
881         return STT_FILE_ERROR_NONE;
882 }
883
884 int stt_file_cancel()
885 {
886         SLOG(LOG_DEBUG, TAG_STTFC, "===== STT FILE CANCEL");
887
888         stt_file_client_s* client = stt_file_client_get();
889
890         /* check handle */
891         if (NULL == client) {
892                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] A handle is not available");
893                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
894                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
895                 return STT_FILE_ERROR_INVALID_PARAMETER;
896         }       
897
898         /* check state */
899         if (STT_FILE_STATE_PROCESSING != client->current_state) {
900                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Invalid state : Current state is NOT 'Processing'");
901                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
902                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
903                 return STT_FILE_ERROR_INVALID_STATE;
904         }
905
906         int ret = -1;
907         ret = stt_engine_recognize_cancel_file(client->current_engine_id);
908         if (0 != ret) {
909                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Fail to cancel file recognition");
910                 SLOG(LOG_DEBUG, TAG_STTFC, "=====");
911                 SLOG(LOG_DEBUG, TAG_STTFC, " ");
912                 return STT_FILE_ERROR_OPERATION_FAILED;
913         }
914
915         client->before_state = client->current_state;
916         client->current_state = STT_FILE_STATE_READY;
917
918         if (NULL != client->state_changed_cb) {
919                 stt_file_client_use_callback(client);
920                 client->state_changed_cb(client->before_state, client->current_state, client->state_changed_user_data); 
921                 stt_file_client_not_use_callback(client);
922                 SLOG(LOG_DEBUG, TAG_STTFC, "State changed callback is called");
923         } else {
924                 SLOG(LOG_WARN, TAG_STTFC, "[WARNING] State changed callback is null");
925         }
926
927         SLOG(LOG_DEBUG, TAG_STTFC, "=====");
928         SLOG(LOG_DEBUG, TAG_STTFC, " ");
929
930         return STT_FILE_ERROR_NONE;
931 }
932
933 bool __stt_file_result_time_cb(int index, sttp_result_time_event_e event, const char* text, long start_time, long end_time, void* user_data) 
934 {
935         SLOG(LOG_DEBUG, TAG_STTFC, "(%d) event(%d) text(%s) start(%ld) end(%ld)",
936                         index, event, text, start_time, end_time);
937
938         stt_file_client_s* client = stt_file_client_get();
939
940         /* check handle */
941         if (NULL == client) {
942                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Fail to notify error : A handle is not valid");
943                 return EINA_FALSE;
944         }
945
946         if (NULL != client->result_time_cb) {
947                 client->result_time_cb(index, (stt_file_result_time_event_e)event, 
948                         text, start_time, end_time, client->result_time_user_data);
949         } else {
950                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Callback is NULL");
951                 return false;
952         }
953
954         return true;
955 }
956
957 int stt_file_foreach_detailed_result(stt_file_result_time_cb callback, void* user_data)
958 {
959         SLOG(LOG_DEBUG, TAG_STTFC, "===== STT FILE FOREACH DETAILED RESULT");
960
961         if (NULL == callback) {
962                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Input parameter is NULL");
963                 return STT_FILE_ERROR_INVALID_PARAMETER;
964         }
965
966         stt_file_client_s* client = stt_file_client_get();
967
968         /* check handle */
969         if (NULL == client) {
970                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Fail : A handle is not valid");
971                 return STT_FILE_ERROR_INVALID_PARAMETER;
972         }
973
974         client->result_time_cb = callback;
975         client->result_time_user_data = user_data;
976
977         stt_engine_foreach_result_time(client->current_engine_id, client->time_info, __stt_file_result_time_cb, NULL);
978
979         client->result_time_cb = NULL;
980         client->result_time_user_data = NULL;
981
982         SLOG(LOG_DEBUG, TAG_STTFC, "=====");
983         SLOG(LOG_DEBUG, TAG_STTFC, " ");
984
985         return STT_FILE_ERROR_NONE;
986 }
987
988 int stt_file_set_recognition_result_cb(stt_file_recognition_result_cb callback, void* user_data)
989 {
990         if (NULL == callback)
991                 return STT_FILE_ERROR_INVALID_PARAMETER;
992
993         stt_file_client_s* client = stt_file_client_get();
994
995         /* check handle */
996         if (NULL == client) {
997                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] A handle is not available");
998                 return STT_FILE_ERROR_INVALID_PARAMETER;
999         }
1000
1001         if (STT_FILE_STATE_READY != client->current_state) {
1002                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Current state is not 'ready'");
1003                 return STT_FILE_ERROR_INVALID_STATE;
1004         }
1005
1006         client->recognition_result_cb = callback;
1007         client->recognition_result_user_data = user_data;
1008
1009         return 0;
1010 }
1011
1012 int stt_file_unset_recognition_result_cb()
1013 {
1014         stt_file_client_s* client = stt_file_client_get();
1015
1016         /* check handle */
1017         if (NULL == client) {
1018                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] A handle is not available");
1019                 return STT_FILE_ERROR_INVALID_PARAMETER;
1020         }
1021
1022         if (STT_FILE_STATE_READY != client->current_state) {
1023                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Current state is not 'ready'");
1024                 return STT_FILE_ERROR_INVALID_STATE;
1025         }
1026
1027         client->recognition_result_cb = NULL;
1028         client->recognition_result_user_data = NULL;
1029
1030         return 0;
1031 }
1032
1033 int stt_file_set_state_changed_cb(stt_file_state_changed_cb callback, void* user_data)
1034 {
1035         if (NULL == callback)
1036                 return STT_FILE_ERROR_INVALID_PARAMETER;
1037
1038         stt_file_client_s* client = stt_file_client_get();
1039
1040         /* check handle */
1041         if (NULL == client) {
1042                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] A handle is not available");
1043                 return STT_FILE_ERROR_INVALID_PARAMETER;
1044         }
1045
1046         if (STT_FILE_STATE_READY != client->current_state) {
1047                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Current state is not 'ready'");
1048                 return STT_FILE_ERROR_INVALID_STATE;
1049         }
1050
1051         client->state_changed_cb = callback;
1052         client->state_changed_user_data = user_data;
1053
1054         return 0;
1055 }
1056
1057 int stt_file_unset_state_changed_cb()
1058 {
1059         stt_file_client_s* client = stt_file_client_get();
1060
1061         /* check handle */
1062         if (NULL == client) {
1063                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] A handle is not available");
1064                 return STT_FILE_ERROR_INVALID_PARAMETER;
1065         }
1066
1067         if (STT_FILE_STATE_READY != client->current_state) {
1068                 SLOG(LOG_ERROR, TAG_STTFC, "[ERROR] Current state is not 'ready'");
1069                 return STT_FILE_ERROR_INVALID_STATE;
1070         }
1071
1072         client->state_changed_cb = NULL;
1073         client->state_changed_user_data = NULL;
1074
1075         return 0;
1076 }