Add internal state for prevent bug from async api call
[platform/core/uifw/voice-control.git] / server / vcd_engine_agent.c
1 /*
2 * Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 #include <dlfcn.h>
19 #include <dirent.h>
20
21 #include "vcd_client_data.h"
22 #include "vcd_config.h"
23 #include "vcd_engine_agent.h"
24 #include "vcd_main.h"
25 #include "vcd_recorder.h"
26
27 /*
28 * Internal data structure
29 */
30 typedef struct {
31         /* engine info */
32         char*   engine_uuid;
33         char*   engine_name;
34         char*   engine_path;
35
36         /* engine load info */
37         bool    is_set;
38         bool    is_loaded;
39         bool    is_command_ready;
40         void    *handle;
41
42         vcpe_funcs_s*   pefuncs;
43         vcpd_funcs_s*   pdfuncs;
44
45         int (*vcp_load_engine)(vcpd_funcs_s* pdfuncs, vcpe_funcs_s* pefuncs);
46         int (*vcp_unload_engine)();
47 } vcengine_s;
48
49 typedef struct _vcengine_info {
50         char*   engine_uuid;
51         char*   engine_path;
52         char*   engine_name;
53 } vcengine_info_s;
54
55
56 /*
57 * static data
58 */
59
60 /** vc engine agent init */
61 static bool g_agent_init;
62
63 /** vc engine list */
64 static GList *g_engine_list;
65
66 /** current engine information */
67 static vcengine_s g_dynamic_engine;
68
69 static char* g_default_lang;
70
71 /** callback functions */
72 static result_callback g_result_cb = NULL;
73
74 static asr_result_callback g_asr_result_cb = NULL;
75
76 #if 0
77 static pre_result_callback g_pre_result_cb = NULL;
78
79 static nlu_result_callback g_nlu_result_cb = NULL;
80 #endif
81
82 static error_callback g_error_cb = NULL;
83
84 bool __supported_language_cb(const char* language, void* user_data);
85
86 void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* engine_setting, bool use_network, void* user_data);
87
88 bool __engine_setting_cb(const char* key, const char* value, void* user_data);
89
90 /** Free voice list */
91 void __free_language_list(GList* lang_list);
92
93
94 /*
95 * Internal Interfaces
96 */
97
98 /** check engine id */
99 int __internal_check_engine_id(const char* engine_uuid);
100
101 /** update engine list */
102 int __internal_update_engine_list();
103
104 /** get engine info */
105 int __internal_get_engine_info(const char* filepath, vcengine_info_s** info);
106
107 int __log_enginelist();
108
109 /*
110 * VCS Engine Agent Interfaces
111 */
112 //int vcd_engine_agent_init(pre_result_callback pre_result_cb, result_callback result_cb, nlu_result_callback nlu_result_cb, error_callback error_cb)
113 int vcd_engine_agent_init(asr_result_callback asr_result_cb, result_callback result_cb, error_callback error_cb)
114 {
115         if (/*NULL == pre_result_cb*/ NULL == asr_result_cb || NULL == result_cb /*|| NULL == nlu_result_cb*/ || NULL == error_cb) {
116                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Input parameter is NULL");
117                 return VCD_ERROR_OPERATION_FAILED;
118         }
119
120         /* init dynamic engine */
121         g_dynamic_engine.engine_uuid = NULL;
122         g_dynamic_engine.engine_name = NULL;
123         g_dynamic_engine.engine_path = NULL;
124
125         g_dynamic_engine.is_set = false;
126         g_dynamic_engine.is_loaded = false;
127         g_dynamic_engine.handle = NULL;
128         g_dynamic_engine.is_command_ready = false;
129         g_dynamic_engine.pefuncs = (vcpe_funcs_s*)calloc(1, sizeof(vcpe_funcs_s));
130         g_dynamic_engine.pdfuncs = (vcpd_funcs_s*)calloc(1, sizeof(vcpd_funcs_s));
131
132         g_agent_init = true;
133
134         //g_pre_result_cb = pre_result_cb;
135         g_asr_result_cb = asr_result_cb;
136         g_result_cb = result_cb;
137         //g_nlu_result_cb = nlu_result_cb;
138         g_error_cb = error_cb;
139
140         if (0 != vcd_config_get_default_language(&g_default_lang)) {
141                 SLOG(LOG_WARN, TAG_VCD, "[Server WARNING] There is No default voice in config");
142                 /* Set default voice */
143                 g_default_lang = strdup(VC_BASE_LANGUAGE);
144         }
145
146         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] Engine Agent Initialize");
147
148         return 0;
149 }
150
151 int vcd_engine_agent_release()
152 {
153         if (false == g_agent_init) {
154                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
155                 return VCD_ERROR_OPERATION_FAILED;
156         }
157
158         /* unload current engine */
159         vcd_engine_agent_unload_current_engine();
160
161         /* release engine list */
162         GList *iter = NULL;
163         vcengine_s *data = NULL;
164
165         if (g_list_length(g_engine_list) > 0) {
166                 /* Get a first item */
167                 iter = g_list_first(g_engine_list);
168
169                 while (NULL != iter) {
170                         /* Get handle data from list */
171                         data = iter->data;
172                         iter = g_list_remove(iter, data);
173                 }
174         }
175
176         g_list_free(iter);
177
178         /* release current engine data */
179         if (NULL != g_dynamic_engine.pefuncs) {
180                 free(g_dynamic_engine.pefuncs);
181                 g_dynamic_engine.pefuncs = NULL;
182         }
183         if (NULL != g_dynamic_engine.pdfuncs) {
184                 free(g_dynamic_engine.pdfuncs);
185                 g_dynamic_engine.pdfuncs = NULL;
186         }
187
188         g_agent_init = false;
189
190         //g_pre_result_cb = NULL;
191         g_asr_result_cb = NULL;
192         g_result_cb = NULL;
193         //g_nlu_result_cb = NULL;
194         g_error_cb = NULL;
195
196         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] Engine Agent release");
197
198         return 0;
199 }
200
201 bool vcd_engine_is_available_engine()
202 {
203         if (true == g_dynamic_engine.is_loaded)
204                 return true;
205
206         return false;
207 }
208
209 int vcd_engine_agent_initialize_current_engine()
210 {
211         /* check agent init */
212         if (false == g_agent_init) {
213                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
214                 return VCD_ERROR_OPERATION_FAILED;
215         }
216
217         /* update engine list */
218         if (0 != __internal_update_engine_list()) {
219                 SLOG(LOG_ERROR, TAG_VCD, "[engine agent] vcd_engine_agent_init : __internal_update_engine_list : no engine error");
220                 return VCD_ERROR_ENGINE_NOT_FOUND;
221         }
222
223         /* check whether engine id is valid or not.*/
224         GList *iter = NULL;
225         vcengine_info_s *dynamic_engine = NULL;
226
227         if (g_list_length(g_engine_list) > 0) {
228                 /*Get a first item*/
229                 iter = g_list_first(g_engine_list);
230
231                 while (NULL != iter) {
232                         /*Get handle data from list*/
233                         dynamic_engine = iter->data;
234                         if (NULL != dynamic_engine) {
235                                 break;
236                         }
237
238                         /*Get next item*/
239                         iter = g_list_next(iter);
240                 }
241         } else {
242                 return VCD_ERROR_ENGINE_NOT_FOUND;
243         }
244
245         if (NULL == dynamic_engine) {
246                 return VCD_ERROR_ENGINE_NOT_FOUND;
247         } else {
248                 if (NULL != g_dynamic_engine.engine_uuid) {
249                         /* set data from g_engine_list */
250                         if (g_dynamic_engine.engine_uuid != NULL)       free(g_dynamic_engine.engine_uuid);
251                         if (g_dynamic_engine.engine_name != NULL)       free(g_dynamic_engine.engine_name);
252                         if (g_dynamic_engine.engine_path != NULL)       free(g_dynamic_engine.engine_path);
253                 }
254
255                 g_dynamic_engine.engine_uuid = g_strdup(dynamic_engine->engine_uuid);
256                 g_dynamic_engine.engine_name = g_strdup(dynamic_engine->engine_name);
257                 g_dynamic_engine.engine_path = g_strdup(dynamic_engine->engine_path);
258
259                 g_dynamic_engine.handle = NULL;
260                 g_dynamic_engine.is_loaded = false;
261                 g_dynamic_engine.is_set = true;
262
263                 SLOG(LOG_DEBUG, TAG_VCD, "-----");
264                 SLOG(LOG_DEBUG, TAG_VCD, " Dynamic engine uuid : %s", g_dynamic_engine.engine_uuid);
265                 SLOG(LOG_DEBUG, TAG_VCD, " Dynamic engine name : %s", g_dynamic_engine.engine_name);
266                 SLOG(LOG_DEBUG, TAG_VCD, " Dynamic engine path : %s", g_dynamic_engine.engine_path);
267                 SLOG(LOG_DEBUG, TAG_VCD, "-----");
268
269         }
270
271         return 0;
272 }
273
274 int __internal_check_engine_id(const char* engine_uuid)
275 {
276         if (NULL == engine_uuid) {
277                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
278                 return VCD_ERROR_INVALID_PARAMETER;
279         }
280
281         GList *iter = NULL;
282         vcengine_s *data = NULL;
283
284         if (0 < g_list_length(g_engine_list)) {
285                 /*Get a first item*/
286                 iter = g_list_first(g_engine_list);
287
288                 while (NULL != iter) {
289                         data = iter->data;
290
291                         if (0 == strncmp(engine_uuid, data->engine_uuid, strlen(data->engine_uuid))) {
292                                 return 0;
293                         }
294
295                         iter = g_list_next(iter);
296                 }
297         }
298
299         return -1;
300 }
301
302 void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* engine_setting, bool use_network, void* user_data)
303 {
304         vcengine_info_s* temp = (vcengine_info_s*)user_data;
305
306         temp->engine_uuid = g_strdup(engine_uuid);
307         temp->engine_name = g_strdup(engine_name);
308 }
309
310
311 int __internal_get_engine_info(const char* filepath, vcengine_info_s** info)
312 {
313         if (NULL == filepath || NULL == info) {
314                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
315                 return VCD_ERROR_INVALID_PARAMETER;
316         }
317
318         /* load engine */
319         char *error;
320         void* handle;
321
322         handle = dlopen(filepath, RTLD_LAZY);
323         if (!handle) {
324                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent] Invalid engine : %s", filepath);
325                 if ((error = dlerror()) != NULL) {
326                         SLOG(LOG_ERROR, TAG_VCD, "[ERROR] %s", error);
327                 }
328                 return -1;
329         }
330
331         /* link engine to daemon */
332         dlsym(handle, "vcp_load_engine");
333         if ((error = dlerror()) != NULL) {
334                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent] Invalid engine. Fail to open vcp_load_engine : %s", filepath);
335                 dlclose(handle);
336                 return -1;
337         }
338
339         dlsym(handle, "vcp_unload_engine");
340         if ((error = dlerror()) != NULL) {
341                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent] Invalid engine. Fail to open vcp_unload_engine : %s", filepath);
342                 dlclose(handle);
343                 return -1;
344         }
345
346         int (*get_engine_info)(vcpe_engine_info_cb callback, void* user_data);
347
348         get_engine_info = (int (*)(vcpe_engine_info_cb, void*))dlsym(handle, "vcp_get_engine_info");
349         if (NULL != (error = dlerror()) || NULL == get_engine_info) {
350                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent WARNING] Invalid engine. Fail to open vcp_get_engine_info : %s", filepath);
351                 dlclose(handle);
352                 return -1;
353         }
354
355         vcengine_info_s* temp;
356         temp = (vcengine_info_s*)calloc(1, sizeof(vcengine_info_s));
357         if (NULL == temp) {
358                 SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to allocate memory");
359                 dlclose(handle);
360                 return VCD_ERROR_OUT_OF_MEMORY;
361         }
362
363         /* get engine info */
364         if (0 != get_engine_info(__engine_info_cb, (void*)temp)) {
365                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to get engine info from engine");
366                 dlclose(handle);
367                 free(temp);
368                 return -1;
369         }
370
371         /* close engine */
372         dlclose(handle);
373
374         temp->engine_path = g_strdup(filepath);
375
376         SLOG(LOG_DEBUG, TAG_VCD, "----- Valid Engine");
377         SLOG(LOG_DEBUG, TAG_VCD, "Engine uuid : %s", temp->engine_uuid);
378         SLOG(LOG_DEBUG, TAG_VCD, "Engine name : %s", temp->engine_name);
379         SLOG(LOG_DEBUG, TAG_VCD, "Engine path : %s", temp->engine_path);
380         SLOG(LOG_DEBUG, TAG_VCD, "-----");
381         SLOG(LOG_DEBUG, TAG_VCD, "  ");
382
383         *info = temp;
384
385         return 0;
386 }
387
388 int __internal_update_engine_list()
389 {
390         /* relsease engine list */
391         GList *iter = NULL;
392         vcengine_info_s *data = NULL;
393
394         if (0 < g_list_length(g_engine_list)) {
395                 /* Get a first item */
396                 iter = g_list_first(g_engine_list);
397
398                 while (NULL != iter) {
399                         /* Get handle data from list */
400                         data = iter->data;
401
402                         if (NULL != data) {
403                                 if (NULL != data->engine_uuid)          free(data->engine_uuid);
404                                 if (NULL != data->engine_path)          free(data->engine_path);
405                                 if (NULL != data->engine_name)          free(data->engine_name);
406
407                                 free(data);
408                         }
409
410                         g_engine_list = g_list_remove_link(g_engine_list, iter);
411                         iter = g_list_first(g_engine_list);
412                 }
413         }
414
415         /* Get file name from default engine directory */
416         DIR *dp = NULL;
417         int ret = -1;
418         struct dirent entry;
419         struct dirent *dirp = NULL;
420
421         dp  = opendir(VC_DEFAULT_ENGINE);
422         if (NULL != dp) {
423                 do {
424                         ret = readdir_r(dp, &entry, &dirp);
425                         if (0 != ret) {
426                                 SLOG(LOG_ERROR, TAG_VCD, "[File ERROR] Fail to read directory");
427                                 break;
428                         }
429
430                         if (NULL != dirp) {
431                                 if (!strcmp(".", dirp->d_name) || !strcmp("..", dirp->d_name))
432                                         continue;
433
434                                 vcengine_info_s* info = NULL;
435                                 char* filepath = NULL;
436                                 int filesize = 0;
437
438                                 filesize = strlen(VC_DEFAULT_ENGINE) + strlen(dirp->d_name) + 5;
439                                 filepath = (char*)calloc(filesize, sizeof(char));
440
441                                 if (NULL != filepath) {
442                                         snprintf(filepath, filesize, "%s/%s", VC_DEFAULT_ENGINE, dirp->d_name);
443                                 } else {
444                                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Memory not enough!!");
445                                         continue;
446                                 }
447
448                                 /* get its info and update engine list */
449                                 if (0 == __internal_get_engine_info(filepath, &info)) {
450                                         /* add engine info to g_engine_list */
451                                         g_engine_list = g_list_append(g_engine_list, info);
452                                 }
453
454                                 if (NULL != filepath) {
455                                         free(filepath);
456                                         filepath = NULL;
457                                 }
458                         }
459                 } while (NULL != dirp);
460
461                 closedir(dp);
462         } else {
463                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent WARNING] Fail to open default directory");
464         }
465
466         if (0 >= g_list_length(g_engine_list)) {
467                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] No Engine");
468                 return VCD_ERROR_ENGINE_NOT_FOUND;
469         }
470
471         __log_enginelist();
472
473         return 0;
474 }
475
476
477 int __foreach_command(vcp_cmd_h vc_command, vcpd_foreach_command_cb callback, void* user_data)
478 {
479         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Request foreach command from engine");
480         return vcd_client_foreach_command((client_foreach_command_cb)callback, user_data);
481 }
482
483 int __command_get_length(vcp_cmd_h vc_command)
484 {
485         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Request command length from engine");
486         return vcd_client_get_length();
487 }
488
489 int __get_audio_type(char** audio_type)
490 {
491         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Request audio type");
492
493         return vcd_recorder_get(audio_type);
494 }
495
496 void __result_cb(vcp_result_event_e event, int* result_id, int count, const char* all_result, const char* non_fixed, const char* nlu_result, const char* msg, void *user_data)
497 {
498         SLOG(LOG_DEBUG, TAG_VCD, "[Engine agent] Event(%d), Count(%d) Text(%s) Nonfixed(%s) NLU result(%s) Msg(%s)", event, count, all_result, non_fixed, nlu_result, msg);
499
500         if (NULL != g_result_cb) {
501                 g_result_cb(event, result_id, count, all_result, non_fixed, nlu_result, msg, user_data);
502         } else {
503                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent ERROR] Result callback function is NOT valid");
504         }
505
506         return;
507 }
508
509 void __asr_result_cb(vcp_asr_result_event_e event, const char* asr_result, void *user_data)
510 {
511         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] ASR result -  Event(%d), Result(%s)", event, asr_result);
512
513         if (NULL != g_asr_result_cb) {
514                 g_asr_result_cb(event, asr_result, user_data);
515         } else {
516                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent ERROR] ASR result callback function is NOT valid");
517         }
518
519         return;
520 }
521
522 void __error_cb(vcp_error_e error, const char* msg, void *user_data)
523 {
524         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] ERROR(%d)", error);
525
526         if (NULL != g_error_cb) {
527                 g_error_cb(error, msg, user_data);
528         } else {
529                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent ERROR] Error callback function is NOT vaild");
530         }
531
532         return;
533 }
534
535 int __load_engine(vcengine_s* engine)
536 {
537         /* check whether current engine is loaded or not */
538         if (true == engine->is_loaded) {
539                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Engine has already been loaded ");
540                 return 0;
541         }
542
543         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Current engine path : %s", engine->engine_path);
544
545         /* open engine */
546         char *error;
547         engine->handle = dlopen(engine->engine_path, RTLD_LAZY);
548
549         if ((error = dlerror()) != NULL || !engine->handle) {
550                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to get engine handle");
551                 return VCD_ERROR_OPERATION_FAILED;
552         }
553
554         engine->vcp_unload_engine = (int (*)())dlsym(engine->handle, "vcp_unload_engine");
555         if ((error = dlerror()) != NULL) {
556                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to link daemon to vcp_unload_engine()");
557                 dlclose(engine->handle);
558                 return VCD_ERROR_OPERATION_FAILED;
559         }
560
561         engine->vcp_load_engine = (int (*)(vcpd_funcs_s*, vcpe_funcs_s*))dlsym(engine->handle, "vcp_load_engine");
562         if (NULL != (error = dlerror()) || NULL == engine->vcp_load_engine) {
563                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to link daemon to vcp_load_engine()");
564                 dlclose(engine->handle);
565                 return VCD_ERROR_OPERATION_FAILED;
566         }
567
568         /* load engine */
569         engine->pdfuncs->version = 1;
570         engine->pdfuncs->size = sizeof(vcpd_funcs_s);
571
572         engine->pdfuncs->foreach_command = __foreach_command;
573         engine->pdfuncs->get_command_count = __command_get_length;
574         engine->pdfuncs->get_audio_type = __get_audio_type;
575
576         if (0 != engine->vcp_load_engine(engine->pdfuncs, engine->pefuncs)) {
577                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail vcp_load_engine()");
578                 dlclose(engine->handle);
579                 return VCD_ERROR_OPERATION_FAILED;
580         }
581
582         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] engine info : version(%d), size(%d)", engine->pefuncs->version, engine->pefuncs->size);
583
584         /* engine error check */
585         if (engine->pefuncs->size != sizeof(vcpe_funcs_s)) {
586                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not valid");
587                 return VCD_ERROR_OPERATION_FAILED;
588         }
589
590         /* Check all engine functions */
591         if (NULL == engine->pefuncs->initialize ||
592                 NULL == engine->pefuncs->deinitialize ||
593                 NULL == engine->pefuncs->get_recording_format ||
594                 NULL == engine->pefuncs->foreach_langs ||
595                 NULL == engine->pefuncs->is_lang_supported ||
596                 NULL == engine->pefuncs->set_result_cb ||
597                 NULL == engine->pefuncs->set_language ||
598                 NULL == engine->pefuncs->set_commands ||
599                 NULL == engine->pefuncs->unset_commands ||
600                 NULL == engine->pefuncs->start ||
601                 NULL == engine->pefuncs->set_recording ||
602                 NULL == engine->pefuncs->stop ||
603                 NULL == engine->pefuncs->cancel ||
604                 NULL == engine->pefuncs->set_asr_result_cb ||
605                 //NULL == engine->pefuncs->set_pre_result_cb ||
606                 NULL == engine->pefuncs->set_error_cb ||
607                 NULL == engine->pefuncs->set_domain ||
608                 NULL == engine->pefuncs->get_nlu_base_info ||
609                 //NULL == engine->pefuncs->set_nlu_result_cb ||
610                 NULL == engine->pefuncs->set_private_data ||
611                 NULL == engine->pefuncs->get_private_data ||
612                 NULL == engine->pefuncs->process_text ||
613                 NULL == engine->pefuncs->process_list_event ||
614                 NULL == engine->pefuncs->process_haptic_event) {
615                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] The current engine is NOT valid");
616                 return VCD_ERROR_OPERATION_FAILED;
617         }
618
619         /* initalize engine */
620         if (0 != engine->pefuncs->initialize()) {
621                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to initialize vc-engine");
622                 return VCD_ERROR_OPERATION_FAILED;
623         }
624
625         if (0 != engine->pefuncs->set_result_cb(__result_cb, NULL)) {
626                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set result callback of vc-engine");
627                 return VCD_ERROR_OPERATION_FAILED;
628         }
629
630         if (0 != engine->pefuncs->set_asr_result_cb(__asr_result_cb, NULL)) {
631                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set asr result callback of vc-engine");
632                 return VCD_ERROR_OPERATION_FAILED;
633         }
634
635         if (0 != engine->pefuncs->set_error_cb(__error_cb, NULL)) {
636                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set error callback of vc-engine");
637                 return VCD_ERROR_OPERATION_FAILED;
638         }
639
640         /* load engine */
641         if (true == engine->pefuncs->is_lang_supported(g_default_lang)) {
642                 if (0 != engine->pefuncs->set_language(g_default_lang)) {
643                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to load current engine");
644                         return VCD_ERROR_OPERATION_FAILED;
645                 }
646                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] The %s has been loaded !!!", engine->engine_name);
647                 engine->is_loaded = true;
648         } else {
649                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent WARNING] This engine do not support default language : lang(%s)", g_default_lang);
650                 engine->is_loaded = false;
651         }
652
653         return 0;
654 }
655
656 int vcd_engine_agent_load_current_engine()
657 {
658         if (false == g_agent_init) {
659                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
660                 return VCD_ERROR_OPERATION_FAILED;
661         }
662
663         if (true == g_dynamic_engine.is_set) {
664                 if (0 != __load_engine(&g_dynamic_engine)) {
665                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to load dynamic engine");
666
667                         /* need to initialize dynamic engine data */
668                         g_dynamic_engine.is_loaded = false;
669                 } else {
670                         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] Load dynamic engine");
671                 }
672         }
673
674         return 0;
675 }
676
677 int vcd_engine_agent_unload_current_engine()
678 {
679         if (false == g_agent_init) {
680                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized ");
681                 return VCD_ERROR_OPERATION_FAILED;
682         }
683
684         if (true == g_dynamic_engine.is_set) {
685                 /* unload dynamic engine */
686                 if (true == g_dynamic_engine.is_loaded) {
687                         /* shutdown engine */
688                         g_dynamic_engine.pefuncs->deinitialize();
689                         g_dynamic_engine.vcp_unload_engine();
690                         dlclose(g_dynamic_engine.handle);
691                         g_dynamic_engine.handle = NULL;
692                         g_dynamic_engine.is_loaded = false;
693                 }
694         }
695         return 0;
696 }
697
698
699 /*
700 * VCS Engine Interfaces for client
701 */
702
703 int vcd_engine_set_commands()
704 {
705         if (false == g_agent_init) {
706                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
707                 return VCD_ERROR_OPERATION_FAILED;
708         }
709
710         int ret = -1;
711
712         if (true == g_dynamic_engine.is_loaded) {
713                 /* Set dynamic command */
714                 ret = g_dynamic_engine.pefuncs->set_commands((vcp_cmd_h)0);
715                 if (0 != ret) {
716                         SLOG(LOG_WARN, TAG_VCD, "[Engine Agent ERROR] Fail to set command of dynamic engine : error(%d)", ret);
717                         g_dynamic_engine.is_command_ready = false;
718                 } else {
719                         g_dynamic_engine.is_command_ready = true;
720                 }
721
722                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] set command");
723         } else {
724                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Dynamic engine is not available");
725         }
726
727         return 0;
728 }
729
730 int vcd_engine_recognize_start(bool silence)
731 {
732         if (false == g_agent_init) {
733                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
734                 return VCD_ERROR_OPERATION_FAILED;
735         }
736
737         int ret = -1;
738         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] silence is %s", silence ? "true" : "false");
739
740         if (true == g_dynamic_engine.is_loaded && true == g_dynamic_engine.is_command_ready) {
741                 ret = g_dynamic_engine.pefuncs->start(silence);
742                 if (0 != ret) {
743                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] Fail to start engine error(%d)", ret);
744                         return VCD_ERROR_OPERATION_FAILED;
745                 }
746         } else {
747                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Engine is not available (Cannot start)");
748                 return VCD_ERROR_OPERATION_FAILED;
749         }
750
751         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] Engine start");
752         return 0;
753 }
754
755 int vcd_engine_recognize_audio(const void* data, unsigned int length, vcp_speech_detect_e* speech_detected)
756 {
757         if (false == g_agent_init) {
758                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
759                 return VCD_ERROR_OPERATION_FAILED;
760         }
761
762         if (NULL == data) {
763                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
764                 return VCD_ERROR_INVALID_PARAMETER;
765         }
766
767         int ret = -1;
768
769         if (true == g_dynamic_engine.is_loaded) {
770                 ret = g_dynamic_engine.pefuncs->set_recording(data, length, speech_detected);
771                 if (0 != ret) {
772                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set recording dynamic engine error(%d)", ret);
773                         if (VCP_ERROR_OUT_OF_NETWORK == ret) {
774                                 return VCD_ERROR_TIMED_OUT;
775                         }
776                         return VCD_ERROR_OPERATION_FAILED;
777                 }
778         }
779
780         return 0;
781 }
782
783 int vcd_engine_recognize_stop()
784 {
785         if (false == g_agent_init) {
786                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
787                 return VCD_ERROR_OPERATION_FAILED;
788         }
789
790         if (true == g_dynamic_engine.is_loaded) {
791                 int ret = -1;
792                 ret = g_dynamic_engine.pefuncs->stop();
793                 if (0 != ret) {
794                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to stop dynamic engine error(%d)", ret);
795                         return VCD_ERROR_OPERATION_FAILED;
796                 }
797         } else {
798                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent] Dynamic engine is not recording state");
799                 return VCD_ERROR_OPERATION_FAILED;
800         }
801
802         return 0;
803 }
804
805 int vcd_engine_recognize_cancel()
806 {
807         if (false == g_agent_init) {
808                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
809                 return VCD_ERROR_OPERATION_FAILED;
810         }
811
812         int ret = -1;
813         if (true == g_dynamic_engine.is_loaded) {
814                 ret = g_dynamic_engine.pefuncs->cancel();
815                 if (0 != ret) {
816                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to cancel dynamic engine error(%d)", ret);
817                         return VCD_ERROR_OPERATION_FAILED;
818                 }
819         }
820
821         return 0;
822 }
823
824 int vcd_engine_set_domain(int pid, const char* domain)
825 {
826         if (false == g_agent_init) {
827                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
828                 return VCD_ERROR_OPERATION_FAILED;
829         }
830
831         int ret = -1;
832         if (true == g_dynamic_engine.is_loaded) {
833                 ret = g_dynamic_engine.pefuncs->set_domain(domain);
834                 if (0 != ret) {
835                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set domain (%d)", ret);
836                         return VCD_ERROR_OPERATION_FAILED;
837                 }
838         }
839
840         return 0;
841 }
842
843 int vcd_engine_get_nlu_base_info(int pid, const char* key, char** value)
844 {
845         if (NULL == value) {
846                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
847                 return VCD_ERROR_INVALID_PARAMETER;
848         }
849
850         if (false == g_agent_init) {
851                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
852                 return VCD_ERROR_OPERATION_FAILED;
853         }
854
855         int ret = -1;
856         if (true == g_dynamic_engine.is_loaded) {
857                 ret = g_dynamic_engine.pefuncs->get_nlu_base_info(key, value);
858                 if (0 != ret) {
859                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to get nlu base info (%d)", ret);
860                         return VCD_ERROR_OPERATION_FAILED;
861                 }
862         }
863
864         return 0;
865 }
866
867 int vcd_engine_set_private_data(int pid, const char* key, const char* data)
868 {
869         if (false == g_agent_init) {
870                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
871                 return VCD_ERROR_OPERATION_FAILED;
872         }
873
874         int ret = -1;
875         if (true == g_dynamic_engine.is_loaded) {
876                 ret = g_dynamic_engine.pefuncs->set_private_data(key, data);
877                 if (0 != ret) {
878                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set private data (%d)", ret);
879                         return VCD_ERROR_OPERATION_FAILED;
880                 }
881         }
882
883         return 0;
884 }
885
886 int vcd_engine_get_private_data(int pid, const char* key, char** data)
887 {
888         if (NULL == data) {
889                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
890                 return VCD_ERROR_INVALID_PARAMETER;
891         }
892
893         if (false == g_agent_init) {
894                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
895                 return VCD_ERROR_OPERATION_FAILED;
896         }
897
898         int ret = -1;
899         if (true == g_dynamic_engine.is_loaded) {
900                 ret = g_dynamic_engine.pefuncs->get_private_data(key, data);
901                 if (0 != ret) {
902                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to get private data (%d)", ret);
903                         return VCD_ERROR_OPERATION_FAILED;
904                 }
905         }
906
907         return 0;
908 }
909
910 int vcd_engine_process_text(int pid, const char* text)
911 {
912         if (false == g_agent_init) {
913                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
914                 return VCD_ERROR_OPERATION_FAILED;
915         }
916
917         int ret = -1;
918         if (true == g_dynamic_engine.is_loaded) {
919                 ret = g_dynamic_engine.pefuncs->process_text(text);
920                 if (0 != ret) {
921                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to process text (%d)", ret);
922                         return VCD_ERROR_OPERATION_FAILED;
923                 }
924         }
925
926         return 0;
927 }
928
929 int vcd_engine_process_list_event(int pid, const char* event)
930 {
931         if (false == g_agent_init) {
932                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
933                 return VCD_ERROR_OPERATION_FAILED;
934         }
935
936         int ret = -1;
937         if (true == g_dynamic_engine.is_loaded) {
938                 ret = g_dynamic_engine.pefuncs->process_list_event(event);
939                 if (0 != ret) {
940                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to process list event (%d)", ret);
941                         return VCD_ERROR_OPERATION_FAILED;
942                 }
943         }
944
945         return 0;
946 }
947
948 int vcd_engine_process_haptic_event(int pid, const char* event)
949 {
950         if (false == g_agent_init) {
951                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
952                 return VCD_ERROR_OPERATION_FAILED;
953         }
954
955         int ret = -1;
956         if (true == g_dynamic_engine.is_loaded) {
957                 ret = g_dynamic_engine.pefuncs->process_haptic_event(event);
958                 if (0 != ret) {
959                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to process haptic event (%d)", ret);
960                         return VCD_ERROR_OPERATION_FAILED;
961                 }
962         }
963
964         return 0;
965 }
966
967 /*
968 * VCS Engine Interfaces for client and setting
969 */
970
971 int vcd_engine_get_audio_format(const char* audio_id, vcp_audio_type_e* types, int* rate, int* channels)
972 {
973         if (false == g_agent_init) {
974                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
975                 return VCD_ERROR_OPERATION_FAILED;
976         }
977
978         if (true != g_dynamic_engine.is_loaded) {
979                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded");
980         }
981
982         if (NULL == g_dynamic_engine.pefuncs->get_recording_format) {
983                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] The function of engine is NULL!!");
984                 return VCD_ERROR_OPERATION_FAILED;
985         }
986
987         int ret = g_dynamic_engine.pefuncs->get_recording_format(audio_id, types, rate, channels);
988         if (0 != ret) {
989                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] get recording format(%d)", ret);
990                 return VCD_ERROR_OPERATION_FAILED;
991         }
992
993         return 0;
994 }
995
996 bool __supported_language_cb(const char* language, void* user_data)
997 {
998         GList** lang_list = (GList**)user_data;
999
1000         if (NULL == language || NULL == lang_list) {
1001                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Input parameter is NULL in callback!!!!");
1002                 return false;
1003         }
1004
1005         SLOG(LOG_DEBUG, TAG_VCD, "-- Language(%s)", language);
1006
1007         char* temp_lang = g_strdup(language);
1008
1009         *lang_list = g_list_append(*lang_list, temp_lang);
1010
1011         return true;
1012 }
1013
1014 int vcd_engine_supported_langs(GList** lang_list)
1015 {
1016         if (false == g_agent_init) {
1017                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
1018                 return VCD_ERROR_OPERATION_FAILED;
1019         }
1020
1021         if (true != g_dynamic_engine.is_loaded) {
1022                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded");
1023         }
1024
1025         if (NULL == g_dynamic_engine.pefuncs->foreach_langs) {
1026                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] The function of engine is NULL!!");
1027                 return VCD_ERROR_OPERATION_FAILED;
1028         }
1029
1030         int ret = g_dynamic_engine.pefuncs->foreach_langs(__supported_language_cb, (void*)lang_list);
1031         if (0 != ret) {
1032                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] get language list error(%d)", ret);
1033                 return VCD_ERROR_OPERATION_FAILED;
1034         }
1035
1036         return 0;
1037 }
1038
1039
1040 int vcd_engine_get_current_language(char** lang)
1041 {
1042         if (false == g_agent_init) {
1043                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
1044                 return VCD_ERROR_OPERATION_FAILED;
1045         }
1046
1047         if (NULL == lang) {
1048                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
1049                 return VCD_ERROR_INVALID_PARAMETER;
1050         }
1051
1052         /* get default language */
1053         *lang = g_strdup(g_default_lang);
1054
1055         return 0;
1056 }
1057
1058 int vcd_engine_set_current_language(const char* language)
1059 {
1060         if (false == g_agent_init) {
1061                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
1062                 return VCD_ERROR_OPERATION_FAILED;
1063         }
1064
1065         if (NULL == language) {
1066                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
1067                 return VCD_ERROR_INVALID_PARAMETER;
1068         }
1069
1070         int ret;
1071
1072         if (true == g_dynamic_engine.is_loaded) {
1073                 g_dynamic_engine.is_command_ready = false;
1074
1075                 ret = g_dynamic_engine.pefuncs->set_language(language);
1076                 if (0 != ret) {
1077                         SLOG(LOG_WARN, TAG_VCD, "[Engine Agent] Fail to set language of dynamic engine error(%d, %s)", ret, language);
1078                 }
1079         } else {
1080                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Dynamic engine is not available (Cannot start)");
1081         }
1082
1083         return 0;
1084 }
1085
1086 void __free_language_list(GList* lang_list)
1087 {
1088         GList *iter = NULL;
1089         char* data = NULL;
1090
1091         /* if list have item */
1092         if (g_list_length(lang_list) > 0) {
1093                 /* Get a first item */
1094                 iter = g_list_first(lang_list);
1095
1096                 while (NULL != iter) {
1097                         data = iter->data;
1098
1099                         if (NULL != data)
1100                                 free(data);
1101
1102                         lang_list = g_list_remove_link(lang_list, iter);
1103
1104                         iter = g_list_first(lang_list);
1105                 }
1106         }
1107 }
1108
1109 int __log_enginelist()
1110 {
1111         GList *iter = NULL;
1112         vcengine_info_s *data = NULL;
1113
1114         if (0 < g_list_length(g_engine_list)) {
1115
1116                 /* Get a first item */
1117                 iter = g_list_first(g_engine_list);
1118
1119                 SLOG(LOG_DEBUG, TAG_VCD, "--------------- engine list -------------------");
1120
1121                 int i = 1;
1122                 while (NULL != iter) {
1123                         /* Get handle data from list */
1124                         data = iter->data;
1125
1126                         SLOG(LOG_DEBUG, TAG_VCD, "[%dth]", i);
1127                         SLOG(LOG_DEBUG, TAG_VCD, "  engine uuid : %s", data->engine_uuid);
1128                         SLOG(LOG_DEBUG, TAG_VCD, "  engine name : %s", data->engine_name);
1129                         SLOG(LOG_DEBUG, TAG_VCD, "  engine path : %s", data->engine_path);
1130                         iter = g_list_next(iter);
1131                         i++;
1132                 }
1133                 SLOG(LOG_DEBUG, TAG_VCD, "----------------------------------------------");
1134         } else {
1135                 SLOG(LOG_DEBUG, TAG_VCD, "-------------- engine list -------------------");
1136                 SLOG(LOG_DEBUG, TAG_VCD, "  No Engine in engine directory");
1137                 SLOG(LOG_DEBUG, TAG_VCD, "----------------------------------------------");
1138         }
1139
1140         return 0;
1141 }
1142
1143
1144
1145