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