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