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