Fix direct leak
[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                                         g_free(data->engine_uuid);
177                                         data->engine_uuid = NULL;
178                                 }
179                                 if (NULL != data->engine_name) {
180                                         g_free(data->engine_name);
181                                         data->engine_name = NULL;
182                                 }
183                                 if (NULL != data->engine_path) {
184                                         g_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)       g_free(g_dynamic_engine.engine_uuid);
270                         if (g_dynamic_engine.engine_name != NULL)       g_free(g_dynamic_engine.engine_name);
271                         if (g_dynamic_engine.engine_path != NULL)       g_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)          g_free(data->engine_uuid);
423                                 if (NULL != data->engine_path)          g_free(data->engine_path);
424                                 if (NULL != data->engine_name)          g_free(data->engine_name);
425
426                                 data->engine_uuid = NULL;
427                                 data->engine_path = NULL;
428                                 data->engine_name = NULL;
429
430                                 free(data);
431                         }
432
433                         g_engine_list = g_list_remove_link(g_engine_list, iter);
434                         iter = g_list_first(g_engine_list);
435                 }
436         }
437
438         /* Get file name from default engine directory */
439         DIR *dp = NULL;
440         struct dirent *dirp = NULL;
441
442         dp  = opendir(VC_DEFAULT_ENGINE);
443         if (NULL != dp) {
444                 do {
445                         dirp = readdir(dp);
446
447                         if (NULL != dirp) {
448                                 if (!strcmp(".", dirp->d_name) || !strcmp("..", dirp->d_name))
449                                         continue;
450
451                                 vcengine_info_s* info = NULL;
452                                 char* filepath = NULL;
453                                 int filesize = 0;
454
455                                 filesize = strlen(VC_DEFAULT_ENGINE) + strlen(dirp->d_name) + 5;
456                                 filepath = (char*)calloc(filesize, sizeof(char));
457
458                                 if (NULL != filepath) {
459                                         snprintf(filepath, filesize, "%s/%s", VC_DEFAULT_ENGINE, dirp->d_name);
460                                 } else {
461                                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Memory not enough!!");
462                                         continue;
463                                 }
464
465                                 /* get its info and update engine list */
466                                 if (0 == __internal_get_engine_info(filepath, &info)) {
467                                         /* add engine info to g_engine_list */
468                                         g_engine_list = g_list_append(g_engine_list, info);
469                                 }
470
471                                 if (NULL != filepath) {
472                                         free(filepath);
473                                         filepath = NULL;
474                                 }
475                         }
476                 } while (NULL != dirp);
477
478                 closedir(dp);
479         } else {
480                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent WARNING] Fail to open default directory");
481         }
482
483         if (0 >= g_list_length(g_engine_list)) {
484                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] No Engine");
485                 return VCD_ERROR_ENGINE_NOT_FOUND;
486         }
487
488         __log_enginelist();
489
490         return 0;
491 }
492
493
494 int __foreach_command(vcp_cmd_h vc_command, vcpd_foreach_command_cb callback, void* user_data)
495 {
496         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Request foreach command from engine");
497         return vcd_client_foreach_command((client_foreach_command_cb)callback, user_data);
498 }
499
500 int __command_get_length(vcp_cmd_h vc_command)
501 {
502         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Request command length from engine");
503         return vcd_client_get_length();
504 }
505
506 int __get_audio_type(char** audio_type)
507 {
508         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Request audio type");
509
510         return vcd_recorder_get(audio_type);
511 }
512
513 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)
514 {
515         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);
516
517         if (NULL != g_result_cb) {
518                 g_result_cb(event, result_id, count, all_result, non_fixed, nlu_result, msg, user_data);
519         } else {
520                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent ERROR] Result callback function is NOT valid");
521         }
522
523         return;
524 }
525
526 void __asr_result_cb(vcp_asr_result_event_e event, const char* asr_result, void *user_data)
527 {
528         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] ASR result -  Event(%d), Result(%s)", event, asr_result);
529
530         if (NULL != g_asr_result_cb) {
531                 g_asr_result_cb(event, asr_result, user_data);
532         } else {
533                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent ERROR] ASR result callback function is NOT valid");
534         }
535
536         return;
537 }
538
539 void __error_cb(vcp_error_e error, const char* msg, void *user_data)
540 {
541         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] ERROR(%d)", error);
542
543         if (NULL != g_error_cb) {
544                 g_error_cb(error, msg, user_data);
545         } else {
546                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent ERROR] Error callback function is NOT vaild");
547         }
548
549         return;
550 }
551
552 int __load_engine(vcengine_s* engine)
553 {
554         /* check whether current engine is loaded or not */
555         if (true == engine->is_loaded) {
556                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Engine has already been loaded ");
557                 return 0;
558         }
559
560         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Current engine path : %s", engine->engine_path);
561
562         /* open engine */
563         char *error;
564         engine->handle = dlopen(engine->engine_path, RTLD_LAZY);
565
566         if ((error = dlerror()) != NULL || !engine->handle) {
567                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to get engine handle");
568                 return VCD_ERROR_OPERATION_FAILED;
569         }
570
571         engine->vcp_unload_engine = (int (*)())dlsym(engine->handle, "vcp_unload_engine");
572         if ((error = dlerror()) != NULL) {
573                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to link daemon to vcp_unload_engine()");
574                 dlclose(engine->handle);
575                 return VCD_ERROR_OPERATION_FAILED;
576         }
577
578         engine->vcp_load_engine = (int (*)(vcpd_funcs_s*, vcpe_funcs_s*))dlsym(engine->handle, "vcp_load_engine");
579         if (NULL != (error = dlerror()) || NULL == engine->vcp_load_engine) {
580                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to link daemon to vcp_load_engine()");
581                 dlclose(engine->handle);
582                 return VCD_ERROR_OPERATION_FAILED;
583         }
584
585         /* load engine */
586         engine->pdfuncs->version = 1;
587         engine->pdfuncs->size = sizeof(vcpd_funcs_s);
588
589         engine->pdfuncs->foreach_command = __foreach_command;
590         engine->pdfuncs->get_command_count = __command_get_length;
591         engine->pdfuncs->get_audio_type = __get_audio_type;
592
593         if (0 != engine->vcp_load_engine(engine->pdfuncs, engine->pefuncs)) {
594                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail vcp_load_engine()");
595                 dlclose(engine->handle);
596                 return VCD_ERROR_OPERATION_FAILED;
597         }
598
599         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] engine info : version(%d), size(%d)", engine->pefuncs->version, engine->pefuncs->size);
600
601         /* engine error check */
602         if (engine->pefuncs->size != sizeof(vcpe_funcs_s)) {
603                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not valid");
604                 return VCD_ERROR_OPERATION_FAILED;
605         }
606
607         /* Check all engine functions */
608         if (NULL == engine->pefuncs->initialize ||
609                 NULL == engine->pefuncs->deinitialize ||
610                 NULL == engine->pefuncs->get_recording_format ||
611                 NULL == engine->pefuncs->foreach_langs ||
612                 NULL == engine->pefuncs->is_lang_supported ||
613                 NULL == engine->pefuncs->set_result_cb ||
614                 NULL == engine->pefuncs->set_language ||
615                 NULL == engine->pefuncs->set_commands ||
616                 NULL == engine->pefuncs->unset_commands ||
617                 NULL == engine->pefuncs->start ||
618                 NULL == engine->pefuncs->set_recording ||
619                 NULL == engine->pefuncs->stop ||
620                 NULL == engine->pefuncs->cancel ||
621                 NULL == engine->pefuncs->set_asr_result_cb ||
622                 //NULL == engine->pefuncs->set_pre_result_cb ||
623                 NULL == engine->pefuncs->set_error_cb ||
624                 NULL == engine->pefuncs->set_domain ||
625                 NULL == engine->pefuncs->get_nlu_base_info ||
626                 //NULL == engine->pefuncs->set_nlu_result_cb ||
627                 NULL == engine->pefuncs->set_private_data ||
628                 NULL == engine->pefuncs->get_private_data ||
629                 NULL == engine->pefuncs->process_text ||
630                 NULL == engine->pefuncs->process_list_event ||
631                 NULL == engine->pefuncs->process_haptic_event) {
632                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] The current engine is NOT valid");
633                 return VCD_ERROR_OPERATION_FAILED;
634         }
635
636         /* initalize engine */
637         if (0 != engine->pefuncs->initialize()) {
638                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to initialize vc-engine");
639                 return VCD_ERROR_OPERATION_FAILED;
640         }
641
642         if (0 != engine->pefuncs->set_result_cb(__result_cb, NULL)) {
643                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set result callback of vc-engine");
644                 return VCD_ERROR_OPERATION_FAILED;
645         }
646
647         if (0 != engine->pefuncs->set_asr_result_cb(__asr_result_cb, NULL)) {
648                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set asr result callback of vc-engine");
649                 return VCD_ERROR_OPERATION_FAILED;
650         }
651
652         if (0 != engine->pefuncs->set_error_cb(__error_cb, NULL)) {
653                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set error callback of vc-engine");
654                 return VCD_ERROR_OPERATION_FAILED;
655         }
656
657         /* load engine */
658         if (true == engine->pefuncs->is_lang_supported(g_default_lang)) {
659                 if (0 != engine->pefuncs->set_language(g_default_lang)) {
660                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to load current engine");
661                         return VCD_ERROR_OPERATION_FAILED;
662                 }
663                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] The %s has been loaded !!!", engine->engine_name);
664                 engine->is_loaded = true;
665         } else {
666                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent WARNING] This engine do not support default language : lang(%s)", g_default_lang);
667                 engine->is_loaded = false;
668         }
669
670         return 0;
671 }
672
673 int vcd_engine_agent_load_current_engine()
674 {
675         if (false == g_agent_init) {
676                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
677                 return VCD_ERROR_OPERATION_FAILED;
678         }
679
680         if (true == g_dynamic_engine.is_set) {
681                 if (0 != __load_engine(&g_dynamic_engine)) {
682                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to load dynamic engine");
683
684                         /* need to initialize dynamic engine data */
685                         g_dynamic_engine.is_loaded = false;
686                 } else {
687                         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] Load dynamic engine");
688                 }
689         }
690
691         return 0;
692 }
693
694 int vcd_engine_agent_unload_current_engine()
695 {
696         if (false == g_agent_init) {
697                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized ");
698                 return VCD_ERROR_OPERATION_FAILED;
699         }
700
701         if (true == g_dynamic_engine.is_set) {
702                 /* unload dynamic engine */
703                 if (true == g_dynamic_engine.is_loaded) {
704                         /* shutdown engine */
705                         g_dynamic_engine.pefuncs->deinitialize();
706                         g_dynamic_engine.vcp_unload_engine();
707                         dlclose(g_dynamic_engine.handle);
708                         g_dynamic_engine.handle = NULL;
709                         g_dynamic_engine.is_loaded = false;
710                 }
711         }
712         return 0;
713 }
714
715
716 /*
717 * VCS Engine Interfaces for client
718 */
719
720 int vcd_engine_set_commands()
721 {
722         if (false == g_agent_init) {
723                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
724                 return VCD_ERROR_OPERATION_FAILED;
725         }
726
727         int ret = -1;
728
729         if (true == g_dynamic_engine.is_loaded) {
730                 /* Set dynamic command */
731                 ret = g_dynamic_engine.pefuncs->set_commands((vcp_cmd_h)0);
732                 if (0 != ret) {
733                         SLOG(LOG_WARN, TAG_VCD, "[Engine Agent ERROR] Fail to set command of dynamic engine : error(%d)", ret);
734                         g_dynamic_engine.is_command_ready = false;
735                 } else {
736                         g_dynamic_engine.is_command_ready = true;
737                 }
738
739                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] set command");
740         } else {
741                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Dynamic engine is not available");
742         }
743
744         return 0;
745 }
746
747 int vcd_engine_recognize_start(bool silence)
748 {
749         if (false == g_agent_init) {
750                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
751                 return VCD_ERROR_OPERATION_FAILED;
752         }
753
754         int ret = -1;
755         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] silence is %s", silence ? "true" : "false");
756
757         if (true == g_dynamic_engine.is_loaded && true == g_dynamic_engine.is_command_ready) {
758                 ret = g_dynamic_engine.pefuncs->start(silence);
759                 if (0 != ret) {
760                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] Fail to start engine error(%d)", ret);
761                         return VCD_ERROR_OPERATION_FAILED;
762                 }
763         } else {
764                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Engine is not available (Cannot start)");
765                 return VCD_ERROR_OPERATION_FAILED;
766         }
767
768         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] Engine start");
769         return 0;
770 }
771
772 int vcd_engine_recognize_audio(const void* data, unsigned int length, vcp_speech_detect_e* speech_detected)
773 {
774         if (false == g_agent_init) {
775                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
776                 return VCD_ERROR_OPERATION_FAILED;
777         }
778
779         if (NULL == data) {
780                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
781                 return VCD_ERROR_INVALID_PARAMETER;
782         }
783
784         int ret = -1;
785
786         if (true == g_dynamic_engine.is_loaded) {
787                 ret = g_dynamic_engine.pefuncs->set_recording(data, length, speech_detected);
788                 if (0 != ret) {
789                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set recording dynamic engine error(%d)", ret);
790                         if (VCP_ERROR_OUT_OF_NETWORK == ret) {
791                                 return VCD_ERROR_TIMED_OUT;
792                         }
793                         return VCD_ERROR_OPERATION_FAILED;
794                 }
795         }
796
797         return 0;
798 }
799
800 int vcd_engine_recognize_stop()
801 {
802         if (false == g_agent_init) {
803                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
804                 return VCD_ERROR_OPERATION_FAILED;
805         }
806
807         if (true == g_dynamic_engine.is_loaded) {
808                 int ret = -1;
809                 ret = g_dynamic_engine.pefuncs->stop();
810                 if (0 != ret) {
811                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to stop dynamic engine error(%d)", ret);
812                         return VCD_ERROR_OPERATION_FAILED;
813                 }
814         } else {
815                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent] Dynamic engine is not recording state");
816                 return VCD_ERROR_OPERATION_FAILED;
817         }
818
819         return 0;
820 }
821
822 int vcd_engine_recognize_cancel()
823 {
824         if (false == g_agent_init) {
825                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
826                 return VCD_ERROR_OPERATION_FAILED;
827         }
828
829         int ret = -1;
830         if (true == g_dynamic_engine.is_loaded) {
831                 ret = g_dynamic_engine.pefuncs->cancel();
832                 if (0 != ret) {
833                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to cancel dynamic engine error(%d)", ret);
834                         return VCD_ERROR_OPERATION_FAILED;
835                 }
836         }
837
838         return 0;
839 }
840
841 int vcd_engine_set_domain(int pid, const char* domain)
842 {
843         if (false == g_agent_init) {
844                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
845                 return VCD_ERROR_OPERATION_FAILED;
846         }
847
848         int ret = -1;
849         if (true == g_dynamic_engine.is_loaded) {
850                 ret = g_dynamic_engine.pefuncs->set_domain(domain);
851                 if (0 != ret) {
852                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set domain (%d)", ret);
853                         return VCD_ERROR_OPERATION_FAILED;
854                 }
855         }
856
857         return 0;
858 }
859
860 int vcd_engine_get_nlu_base_info(int pid, const char* key, char** value)
861 {
862         if (NULL == value) {
863                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
864                 return VCD_ERROR_INVALID_PARAMETER;
865         }
866
867         if (false == g_agent_init) {
868                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
869                 return VCD_ERROR_OPERATION_FAILED;
870         }
871
872         int ret = -1;
873         if (true == g_dynamic_engine.is_loaded) {
874                 ret = g_dynamic_engine.pefuncs->get_nlu_base_info(key, value);
875                 if (0 != ret) {
876                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to get nlu base info (%d)", ret);
877                         return VCD_ERROR_OPERATION_FAILED;
878                 }
879         }
880
881         return 0;
882 }
883
884 int vcd_engine_set_private_data(int pid, const char* key, const char* data)
885 {
886         if (false == g_agent_init) {
887                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
888                 return VCD_ERROR_OPERATION_FAILED;
889         }
890
891         int ret = -1;
892         if (true == g_dynamic_engine.is_loaded) {
893                 ret = g_dynamic_engine.pefuncs->set_private_data(key, data);
894                 if (0 != ret) {
895                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set private data (%d)", ret);
896                         return VCD_ERROR_OPERATION_FAILED;
897                 }
898         }
899
900         return 0;
901 }
902
903 int vcd_engine_get_private_data(int pid, const char* key, char** data)
904 {
905         if (NULL == data) {
906                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
907                 return VCD_ERROR_INVALID_PARAMETER;
908         }
909
910         if (false == g_agent_init) {
911                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
912                 return VCD_ERROR_OPERATION_FAILED;
913         }
914
915         int ret = -1;
916         if (true == g_dynamic_engine.is_loaded) {
917                 ret = g_dynamic_engine.pefuncs->get_private_data(key, data);
918                 if (0 != ret) {
919                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to get private data (%d)", ret);
920                         return VCD_ERROR_OPERATION_FAILED;
921                 }
922         }
923
924         return 0;
925 }
926
927 int vcd_engine_process_text(int pid, const char* text)
928 {
929         if (false == g_agent_init) {
930                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
931                 return VCD_ERROR_OPERATION_FAILED;
932         }
933
934         int ret = -1;
935         if (true == g_dynamic_engine.is_loaded) {
936                 ret = g_dynamic_engine.pefuncs->process_text(text);
937                 if (0 != ret) {
938                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to process text (%d)", ret);
939                         return VCD_ERROR_OPERATION_FAILED;
940                 }
941         }
942
943         return 0;
944 }
945
946 int vcd_engine_process_list_event(int pid, const char* event)
947 {
948         if (false == g_agent_init) {
949                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
950                 return VCD_ERROR_OPERATION_FAILED;
951         }
952
953         int ret = -1;
954         if (true == g_dynamic_engine.is_loaded) {
955                 ret = g_dynamic_engine.pefuncs->process_list_event(event);
956                 if (0 != ret) {
957                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to process list event (%d)", ret);
958                         return VCD_ERROR_OPERATION_FAILED;
959                 }
960         }
961
962         return 0;
963 }
964
965 int vcd_engine_process_haptic_event(int pid, const char* event)
966 {
967         if (false == g_agent_init) {
968                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
969                 return VCD_ERROR_OPERATION_FAILED;
970         }
971
972         int ret = -1;
973         if (true == g_dynamic_engine.is_loaded) {
974                 ret = g_dynamic_engine.pefuncs->process_haptic_event(event);
975                 if (0 != ret) {
976                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to process haptic event (%d)", ret);
977                         return VCD_ERROR_OPERATION_FAILED;
978                 }
979         }
980
981         return 0;
982 }
983
984 /*
985 * VCS Engine Interfaces for client and setting
986 */
987
988 int vcd_engine_get_audio_format(const char* audio_id, vcp_audio_type_e* types, int* rate, int* channels)
989 {
990         if (false == g_agent_init) {
991                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
992                 return VCD_ERROR_OPERATION_FAILED;
993         }
994
995         if (true != g_dynamic_engine.is_loaded) {
996                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded");
997         }
998
999         if (NULL == g_dynamic_engine.pefuncs->get_recording_format) {
1000                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] The function of engine is NULL!!");
1001                 return VCD_ERROR_OPERATION_FAILED;
1002         }
1003
1004         int ret = g_dynamic_engine.pefuncs->get_recording_format(audio_id, types, rate, channels);
1005         if (0 != ret) {
1006                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] get recording format(%d)", ret);
1007                 return VCD_ERROR_OPERATION_FAILED;
1008         }
1009
1010         return 0;
1011 }
1012
1013 bool __supported_language_cb(const char* language, void* user_data)
1014 {
1015         GList** lang_list = (GList**)user_data;
1016
1017         if (NULL == language || NULL == lang_list) {
1018                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Input parameter is NULL in callback!!!!");
1019                 return false;
1020         }
1021
1022         SLOG(LOG_DEBUG, TAG_VCD, "-- Language(%s)", language);
1023
1024         char* temp_lang = g_strdup(language);
1025
1026         *lang_list = g_list_append(*lang_list, temp_lang);
1027
1028         return true;
1029 }
1030
1031 int vcd_engine_supported_langs(GList** lang_list)
1032 {
1033         if (false == g_agent_init) {
1034                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
1035                 return VCD_ERROR_OPERATION_FAILED;
1036         }
1037
1038         if (true != g_dynamic_engine.is_loaded) {
1039                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded");
1040         }
1041
1042         if (NULL == g_dynamic_engine.pefuncs->foreach_langs) {
1043                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] The function of engine is NULL!!");
1044                 return VCD_ERROR_OPERATION_FAILED;
1045         }
1046
1047         int ret = g_dynamic_engine.pefuncs->foreach_langs(__supported_language_cb, (void*)lang_list);
1048         if (0 != ret) {
1049                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] get language list error(%d)", ret);
1050                 return VCD_ERROR_OPERATION_FAILED;
1051         }
1052
1053         return 0;
1054 }
1055
1056
1057 int vcd_engine_get_current_language(char** lang)
1058 {
1059         if (false == g_agent_init) {
1060                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
1061                 return VCD_ERROR_OPERATION_FAILED;
1062         }
1063
1064         if (NULL == lang) {
1065                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
1066                 return VCD_ERROR_INVALID_PARAMETER;
1067         }
1068
1069         /* get default language */
1070         *lang = g_strdup(g_default_lang);
1071
1072         return 0;
1073 }
1074
1075 int vcd_engine_set_current_language(const char* language)
1076 {
1077         if (false == g_agent_init) {
1078                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
1079                 return VCD_ERROR_OPERATION_FAILED;
1080         }
1081
1082         if (NULL == language) {
1083                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
1084                 return VCD_ERROR_INVALID_PARAMETER;
1085         }
1086
1087         int ret;
1088
1089         if (true == g_dynamic_engine.is_loaded) {
1090                 g_dynamic_engine.is_command_ready = false;
1091
1092                 ret = g_dynamic_engine.pefuncs->set_language(language);
1093                 if (0 != ret) {
1094                         SLOG(LOG_WARN, TAG_VCD, "[Engine Agent] Fail to set language of dynamic engine error(%d, %s)", ret, language);
1095                 }
1096         } else {
1097                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Dynamic engine is not available (Cannot start)");
1098         }
1099
1100         return 0;
1101 }
1102
1103 void __free_language_list(GList* lang_list)
1104 {
1105         GList *iter = NULL;
1106         char* data = NULL;
1107
1108         /* if list have item */
1109         if (g_list_length(lang_list) > 0) {
1110                 /* Get a first item */
1111                 iter = g_list_first(lang_list);
1112
1113                 while (NULL != iter) {
1114                         data = iter->data;
1115
1116                         if (NULL != data)
1117                                 free(data);
1118
1119                         lang_list = g_list_remove_link(lang_list, iter);
1120
1121                         iter = g_list_first(lang_list);
1122                 }
1123         }
1124 }
1125
1126 int __log_enginelist()
1127 {
1128         GList *iter = NULL;
1129         vcengine_info_s *data = NULL;
1130
1131         if (0 < g_list_length(g_engine_list)) {
1132
1133                 /* Get a first item */
1134                 iter = g_list_first(g_engine_list);
1135
1136                 SLOG(LOG_DEBUG, TAG_VCD, "--------------- engine list -------------------");
1137
1138                 int i = 1;
1139                 while (NULL != iter) {
1140                         /* Get handle data from list */
1141                         data = iter->data;
1142
1143                         SLOG(LOG_DEBUG, TAG_VCD, "[%dth]", i);
1144                         SLOG(LOG_DEBUG, TAG_VCD, "  engine uuid : %s", data->engine_uuid);
1145                         SLOG(LOG_DEBUG, TAG_VCD, "  engine name : %s", data->engine_name);
1146                         SLOG(LOG_DEBUG, TAG_VCD, "  engine path : %s", data->engine_path);
1147                         iter = g_list_next(iter);
1148                         i++;
1149                 }
1150                 SLOG(LOG_DEBUG, TAG_VCD, "----------------------------------------------");
1151         } else {
1152                 SLOG(LOG_DEBUG, TAG_VCD, "-------------- engine list -------------------");
1153                 SLOG(LOG_DEBUG, TAG_VCD, "  No Engine in engine directory");
1154                 SLOG(LOG_DEBUG, TAG_VCD, "----------------------------------------------");
1155         }
1156
1157         return 0;
1158 }