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