[Code Review] Fix codes
[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 pre_result_callback g_pre_result_cb;
73 static result_callback g_result_cb;
74
75 bool __supported_language_cb(const char* language, void* user_data);
76
77 void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* engine_setting, bool use_network, void* user_data);
78
79 bool __engine_setting_cb(const char* key, const char* value, void* user_data);
80
81 /** Free voice list */
82 void __free_language_list(GList* lang_list);
83
84
85 /*
86 * Internal Interfaces
87 */
88
89 /** check engine id */
90 int __internal_check_engine_id(const char* engine_uuid);
91
92 /** update engine list */
93 int __internal_update_engine_list();
94
95 /** get engine info */
96 int __internal_get_engine_info(const char* filepath, vcengine_info_s** info);
97
98 int __log_enginelist();
99
100 /*
101 * VCS Engine Agent Interfaces
102 */
103 int vcd_engine_agent_init(pre_result_callback pre_cb, result_callback result_cb)
104 {
105         if (NULL == pre_cb || NULL == result_cb) {
106                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Input parameter is NULL");
107                 return VCD_ERROR_OPERATION_FAILED;
108         }
109
110         /* init dynamic engine */
111         g_dynamic_engine.engine_uuid = NULL;
112         g_dynamic_engine.engine_name = NULL;
113         g_dynamic_engine.engine_path = NULL;
114
115         g_dynamic_engine.is_set = false;
116         g_dynamic_engine.is_loaded = false;
117         g_dynamic_engine.handle = NULL;
118         g_dynamic_engine.is_command_ready = false;
119         g_dynamic_engine.pefuncs = (vcpe_funcs_s*)calloc(1, sizeof(vcpe_funcs_s));
120         g_dynamic_engine.pdfuncs = (vcpd_funcs_s*)calloc(1, sizeof(vcpd_funcs_s));
121
122         g_agent_init = true;
123
124         g_pre_result_cb = pre_cb;
125         g_result_cb = result_cb;
126
127         if (0 != vcd_config_get_default_language(&g_default_lang)) {
128                 SLOG(LOG_WARN, TAG_VCD, "[Server WARNING] There is No default voice in config");
129                 /* Set default voice */
130                 g_default_lang = strdup(VC_BASE_LANGUAGE);
131         }
132
133         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] Engine Agent Initialize");
134
135         return 0;
136 }
137
138 int vcd_engine_agent_release()
139 {
140         if (false == g_agent_init) {
141                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
142                 return VCD_ERROR_OPERATION_FAILED;
143         }
144
145         /* unload current engine */
146         vcd_engine_agent_unload_current_engine();
147
148         /* release engine list */
149         GList *iter = NULL;
150         vcengine_s *data = NULL;
151
152         if (g_list_length(g_engine_list) > 0) {
153                 /* Get a first item */
154                 iter = g_list_first(g_engine_list);
155
156                 while (NULL != iter) {
157                         /* Get handle data from list */
158                         data = iter->data;
159                         iter = g_list_remove(iter, data);
160                 }
161         }
162
163         g_list_free(iter);
164
165         /* release current engine data */
166         if (NULL != g_dynamic_engine.pefuncs)   free(g_dynamic_engine.pefuncs);
167         if (NULL != g_dynamic_engine.pdfuncs)   free(g_dynamic_engine.pdfuncs);
168
169         g_agent_init = false;
170
171         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] Engine Agent release");
172
173         return 0;
174 }
175
176 bool vcd_engine_is_available_engine()
177 {
178         if (true == g_dynamic_engine.is_loaded)
179                 return true;
180
181         return false;
182 }
183
184 int vcd_engine_agent_initialize_current_engine()
185 {
186         /* check agent init */
187         if (false == g_agent_init) {
188                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
189                 return VCD_ERROR_OPERATION_FAILED;
190         }
191
192         /* update engine list */
193         if (0 != __internal_update_engine_list()) {
194                 SLOG(LOG_ERROR, TAG_VCD, "[engine agent] vcd_engine_agent_init : __internal_update_engine_list : no engine error");
195                 return VCD_ERROR_ENGINE_NOT_FOUND;
196         }
197
198         /* check whether engine id is valid or not.*/
199         GList *iter = NULL;
200         vcengine_info_s *dynamic_engine = NULL;
201
202         if (g_list_length(g_engine_list) > 0) {
203                 /*Get a first item*/
204                 iter = g_list_first(g_engine_list);
205
206                 while (NULL != iter) {
207                         /*Get handle data from list*/
208                         dynamic_engine = iter->data;
209                         if (NULL != dynamic_engine) {
210                                 break;
211                         }
212
213                         /*Get next item*/
214                         iter = g_list_next(iter);
215                 }
216         } else {
217                 return VCD_ERROR_ENGINE_NOT_FOUND;
218         }
219
220         if (NULL == dynamic_engine) {
221                 return VCD_ERROR_ENGINE_NOT_FOUND;
222         } else {
223                 if (NULL != g_dynamic_engine.engine_uuid) {
224                         /* set data from g_engine_list */
225                         if (g_dynamic_engine.engine_uuid != NULL)       free(g_dynamic_engine.engine_uuid);
226                         if (g_dynamic_engine.engine_name != NULL)       free(g_dynamic_engine.engine_name);
227                         if (g_dynamic_engine.engine_path != NULL)       free(g_dynamic_engine.engine_path);
228                 }
229
230                 g_dynamic_engine.engine_uuid = g_strdup(dynamic_engine->engine_uuid);
231                 g_dynamic_engine.engine_name = g_strdup(dynamic_engine->engine_name);
232                 g_dynamic_engine.engine_path = g_strdup(dynamic_engine->engine_path);
233
234                 g_dynamic_engine.handle = NULL;
235                 g_dynamic_engine.is_loaded = false;
236                 g_dynamic_engine.is_set = true;
237
238                 SLOG(LOG_DEBUG, TAG_VCD, "-----");
239                 SLOG(LOG_DEBUG, TAG_VCD, " Dynamic engine uuid : %s", g_dynamic_engine.engine_uuid);
240                 SLOG(LOG_DEBUG, TAG_VCD, " Dynamic engine name : %s", g_dynamic_engine.engine_name);
241                 SLOG(LOG_DEBUG, TAG_VCD, " Dynamic engine path : %s", g_dynamic_engine.engine_path);
242                 SLOG(LOG_DEBUG, TAG_VCD, "-----");
243
244         }
245
246         return 0;
247 }
248
249 int __internal_check_engine_id(const char* engine_uuid)
250 {
251         if (NULL == engine_uuid) {
252                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
253                 return VCD_ERROR_INVALID_PARAMETER;
254         }
255
256         GList *iter = NULL;
257         vcengine_s *data = NULL;
258
259         if (0 < g_list_length(g_engine_list)) {
260                 /*Get a first item*/
261                 iter = g_list_first(g_engine_list);
262
263                 while (NULL != iter) {
264                         data = iter->data;
265
266                         if (0 == strncmp(engine_uuid, data->engine_uuid, strlen(data->engine_uuid))) {
267                                 return 0;
268                         }
269
270                         iter = g_list_next(iter);
271                 }
272         }
273
274         return -1;
275 }
276
277 void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* engine_setting, bool use_network, void* user_data)
278 {
279         vcengine_info_s* temp = (vcengine_info_s*)user_data;
280
281         temp->engine_uuid = g_strdup(engine_uuid);
282         temp->engine_name = g_strdup(engine_name);
283 }
284
285
286 int __internal_get_engine_info(const char* filepath, vcengine_info_s** info)
287 {
288         if (NULL == filepath || NULL == info) {
289                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
290                 return VCD_ERROR_INVALID_PARAMETER;
291         }
292
293         /* load engine */
294         char *error;
295         void* handle;
296
297         handle = dlopen(filepath, RTLD_LAZY);
298         if (!handle) {
299                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent] Invalid engine : %s", filepath);
300                 return -1;
301         }
302
303         /* link engine to daemon */
304         dlsym(handle, "vcp_load_engine");
305         if ((error = dlerror()) != NULL) {
306                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent] Invalid engine. Fail to open vcp_load_engine : %s", filepath);
307                 dlclose(handle);
308                 return -1;
309         }
310
311         dlsym(handle, "vcp_unload_engine");
312         if ((error = dlerror()) != NULL) {
313                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent] Invalid engine. Fail to open vcp_unload_engine : %s", filepath);
314                 dlclose(handle);
315                 return -1;
316         }
317
318         int (*get_engine_info)(vcpe_engine_info_cb callback, void* user_data);
319
320         get_engine_info = (int (*)(vcpe_engine_info_cb, void*))dlsym(handle, "vcp_get_engine_info");
321         if (NULL != (error = dlerror()) || NULL == get_engine_info) {
322                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent WARNING] Invalid engine. Fail to open vcp_get_engine_info : %s", filepath);
323                 dlclose(handle);
324                 return -1;
325         }
326
327         vcengine_info_s* temp;
328         temp = (vcengine_info_s*)calloc(1, sizeof(vcengine_info_s));
329         if (NULL == temp) {
330                 SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to allocate memory");
331                 dlclose(handle);
332                 return VCD_ERROR_OUT_OF_MEMORY;
333         }
334
335         /* get engine info */
336         if (0 != get_engine_info(__engine_info_cb, (void*)temp)) {
337                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to get engine info from engine");
338                 dlclose(handle);
339                 free(temp);
340                 return -1;
341         }
342
343         /* close engine */
344         dlclose(handle);
345
346         temp->engine_path = g_strdup(filepath);
347
348         SLOG(LOG_DEBUG, TAG_VCD, "----- Valid Engine");
349         SLOG(LOG_DEBUG, TAG_VCD, "Engine uuid : %s", temp->engine_uuid);
350         SLOG(LOG_DEBUG, TAG_VCD, "Engine name : %s", temp->engine_name);
351         SLOG(LOG_DEBUG, TAG_VCD, "Engine path : %s", temp->engine_path);
352         SLOG(LOG_DEBUG, TAG_VCD, "-----");
353         SLOG(LOG_DEBUG, TAG_VCD, "  ");
354
355         *info = temp;
356
357         return 0;
358 }
359
360 int __internal_update_engine_list()
361 {
362         /* relsease engine list */
363         GList *iter = NULL;
364         vcengine_info_s *data = NULL;
365
366         if (0 < g_list_length(g_engine_list)) {
367                 /* Get a first item */
368                 iter = g_list_first(g_engine_list);
369
370                 while (NULL != iter) {
371                         /* Get handle data from list */
372                         data = iter->data;
373
374                         if (NULL != data) {
375                                 if (NULL != data->engine_uuid)          free(data->engine_uuid);
376                                 if (NULL != data->engine_path)          free(data->engine_path);
377                                 if (NULL != data->engine_name)          free(data->engine_name);
378
379                                 free(data);
380                         }
381
382                         g_engine_list = g_list_remove_link(g_engine_list, iter);
383                         iter = g_list_first(g_engine_list);
384                 }
385         }
386
387         /* Get file name from default engine directory */
388         DIR *dp = NULL;
389         int ret = -1;
390         struct dirent entry;
391         struct dirent *dirp = NULL;
392
393         dp  = opendir(VC_DEFAULT_ENGINE);
394         if (NULL != dp) {
395                 do {
396                         ret = readdir_r(dp, &entry, &dirp);
397                         if (0 != ret) {
398                                 SLOG(LOG_ERROR, TAG_VCD, "[File ERROR] Fail to read directory");
399                                 break;
400                         }
401
402                         if (NULL != dirp) {
403                                 vcengine_info_s* info = NULL;
404                                 char* filepath = NULL;
405                                 int filesize = 0;
406
407                                 filesize = strlen(VC_DEFAULT_ENGINE) + strlen(dirp->d_name) + 5;
408                                 filepath = (char*)calloc(filesize, sizeof(char));
409
410                                 if (NULL != filepath) {
411                                         snprintf(filepath, filesize, "%s/%s", VC_DEFAULT_ENGINE, dirp->d_name);
412                                 } else {
413                                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Memory not enough!!");
414                                         continue;
415                                 }
416
417                                 /* get its info and update engine list */
418                                 if (0 == __internal_get_engine_info(filepath, &info)) {
419                                         /* add engine info to g_engine_list */
420                                         g_engine_list = g_list_append(g_engine_list, info);
421                                 }
422
423                                 if (NULL != filepath) {
424                                         free(filepath);
425                                         filepath = NULL;
426                                 }
427                         }
428                 } while (NULL != dirp);
429
430                 closedir(dp);
431         } else {
432                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent WARNING] Fail to open default directory");
433         }
434
435         if (0 >= g_list_length(g_engine_list)) {
436                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] No Engine");
437                 return VCD_ERROR_ENGINE_NOT_FOUND;
438         }
439
440         __log_enginelist();
441
442         return 0;
443 }
444
445
446 int __foreach_command(vcp_cmd_h vc_command, vcpd_foreach_command_cb callback, void* user_data)
447 {
448         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Request foreach command from engine");
449         return vcd_client_foreach_command((client_foreach_command_cb)callback, user_data);
450 }
451
452 int __command_get_length(vcp_cmd_h vc_command)
453 {
454         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Request command length from engine");
455         return vcd_client_get_length();
456 }
457
458 int __get_audio_type(char** audio_type)
459 {
460         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Request audio type");
461
462         return vcd_recorder_get(audio_type);
463 }
464
465 void __pre_result_cb(vcp_pre_result_event_e event, const char* pre_result, void* user_data)
466 {
467         SLOG(LOG_DEBUG, TAG_VCD, "[Engine agent] Pre result(%s)", pre_result);
468
469         if (NULL != g_pre_result_cb) {
470                 g_pre_result_cb(event, pre_result, user_data);
471         } else {
472                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent ERROR] Result callback function is NOT valid");
473         }
474
475 }
476
477 void __result_cb(vcp_result_event_e event, int* result_id, int count, const char* all_result, const char* non_fixed, const char* msg, void *user_data)
478 {
479         SLOG(LOG_DEBUG, TAG_VCD, "[Engine agent] Event(%d), Count(%d) Text(%s) Nonfixed(%s) Msg(%s)", event, count, all_result, non_fixed, msg);
480
481         // Need to nlp info handle or true false value
482         int ret = 0;
483         char* temp_nlp = NULL;
484
485         if (true == g_dynamic_engine.is_loaded) {
486                 if (NULL != g_dynamic_engine.pefuncs->get_nlp_info) {
487                         ret = g_dynamic_engine.pefuncs->get_nlp_info(&temp_nlp);
488                         if (0 != ret) {
489                                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent ERROR] Fail to get nlp info : error(%d)", ret);
490                         } else {
491                                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] Get nlp info : %s", temp_nlp);
492                         }
493                 } else {
494                         SLOG(LOG_WARN, TAG_VCD, "[Engine Agent ERROR] Not support to get nlp info");
495                 }
496         }
497
498         if (NULL == temp_nlp)
499                 temp_nlp = "null";
500
501         if (NULL != g_result_cb) {
502                 g_result_cb(event, result_id, count, all_result, non_fixed, msg, temp_nlp, user_data);
503         } else {
504                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent ERROR] Result callback function is NOT valid");
505         }
506
507         return;
508 }
509
510 int __load_engine(vcengine_s* engine)
511 {
512         /* check whether current engine is loaded or not */
513         if (true == engine->is_loaded) {
514                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Engine has already been loaded ");
515                 return 0;
516         }
517
518         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Current engine path : %s", engine->engine_path);
519
520         /* open engine */
521         char *error;
522         engine->handle = dlopen(engine->engine_path, RTLD_LAZY);
523
524         if ((error = dlerror()) != NULL || !engine->handle) {
525                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to get engine handle");
526                 return VCD_ERROR_OPERATION_FAILED;
527         }
528
529         engine->vcp_unload_engine = (int (*)())dlsym(engine->handle, "vcp_unload_engine");
530         if ((error = dlerror()) != NULL) {
531                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to link daemon to vcp_unload_engine()");
532                 dlclose(engine->handle);
533                 return VCD_ERROR_OPERATION_FAILED;
534         }
535
536         engine->vcp_load_engine = (int (*)(vcpd_funcs_s*, vcpe_funcs_s*))dlsym(engine->handle, "vcp_load_engine");
537         if (NULL != (error = dlerror()) || NULL == engine->vcp_load_engine) {
538                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to link daemon to vcp_load_engine()");
539                 dlclose(engine->handle);
540                 return VCD_ERROR_OPERATION_FAILED;
541         }
542
543         /* load engine */
544         engine->pdfuncs->version = 1;
545         engine->pdfuncs->size = sizeof(vcpd_funcs_s);
546
547         engine->pdfuncs->foreach_command = __foreach_command;
548         engine->pdfuncs->get_command_count = __command_get_length;
549         engine->pdfuncs->get_audio_type = __get_audio_type;
550
551         if (0 != engine->vcp_load_engine(engine->pdfuncs, engine->pefuncs)) {
552                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail vcp_load_engine()");
553                 dlclose(engine->handle);
554                 return VCD_ERROR_OPERATION_FAILED;
555         }
556
557         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] engine info : version(%d), size(%d)", engine->pefuncs->version, engine->pefuncs->size);
558
559         /* engine error check */
560         if (engine->pefuncs->size != sizeof(vcpe_funcs_s)) {
561                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not valid");
562                 return VCD_ERROR_OPERATION_FAILED;
563         }
564
565         /* Check all engine functions */
566         if (NULL == engine->pefuncs->initialize ||
567                 NULL == engine->pefuncs->deinitialize ||
568                 NULL == engine->pefuncs->foreach_langs ||
569                 NULL == engine->pefuncs->is_lang_supported ||
570                 NULL == engine->pefuncs->set_result_cb ||
571                 NULL == engine->pefuncs->set_language ||
572                 NULL == engine->pefuncs->set_recording ||
573                 NULL == engine->pefuncs->stop ||
574                 NULL == engine->pefuncs->cancel) {
575                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] The current engine is NOT valid");
576                 return VCD_ERROR_OPERATION_FAILED;
577         }
578
579         /* initalize engine */
580         if (0 != engine->pefuncs->initialize()) {
581                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to initialize vc-engine");
582                 return VCD_ERROR_OPERATION_FAILED;
583         }
584
585         if (0 != engine->pefuncs->set_result_cb(__result_cb, NULL)) {
586                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set result callback of vc-engine");
587                 return VCD_ERROR_OPERATION_FAILED;
588         }
589
590         // temp
591         if (0 != engine->pefuncs->set_pre_result_cb(__pre_result_cb, NULL)) {
592                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set pre result callback of vc-engine");
593                 return VCD_ERROR_OPERATION_FAILED;
594         }
595
596         /* load engine */
597         if (true == engine->pefuncs->is_lang_supported(g_default_lang)) {
598                 if (0 != engine->pefuncs->set_language(g_default_lang)) {
599                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to load current engine");
600                         return VCD_ERROR_OPERATION_FAILED;
601                 }
602                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] The %s has been loaded !!!", engine->engine_name);
603                 engine->is_loaded = true;
604         } else {
605                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent WARNING] This engine do not support default language : lang(%s)", g_default_lang);
606                 engine->is_loaded = false;
607         }
608
609         return 0;
610 }
611
612 int vcd_engine_agent_load_current_engine()
613 {
614         if (false == g_agent_init) {
615                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
616                 return VCD_ERROR_OPERATION_FAILED;
617         }
618
619         if (true == g_dynamic_engine.is_set) {
620                 if (0 != __load_engine(&g_dynamic_engine)) {
621                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to load dynamic engine");
622
623                         /* need to initialize dynamic engine data */
624                         g_dynamic_engine.is_loaded = false;
625                 } else {
626                         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] Load dynamic engine");
627                 }
628         }
629
630         return 0;
631 }
632
633 int vcd_engine_agent_unload_current_engine()
634 {
635         if (false == g_agent_init) {
636                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized ");
637                 return VCD_ERROR_OPERATION_FAILED;
638         }
639
640         if (true == g_dynamic_engine.is_set) {
641                 /* unload dynamic engine */
642                 if (true == g_dynamic_engine.is_loaded) {
643                         /* shutdown engine */
644                         g_dynamic_engine.pefuncs->deinitialize();
645                         g_dynamic_engine.vcp_unload_engine();
646                         dlclose(g_dynamic_engine.handle);
647                         g_dynamic_engine.handle = NULL;
648                         g_dynamic_engine.is_loaded = false;
649                 }
650         }
651         return 0;
652 }
653
654
655 /*
656 * VCS Engine Interfaces for client
657 */
658
659 int vcd_engine_set_commands()
660 {
661         if (false == g_agent_init) {
662                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
663                 return VCD_ERROR_OPERATION_FAILED;
664         }
665
666         int ret = -1;
667
668         if (true == g_dynamic_engine.is_loaded) {
669                 /* Set dynamic command */
670                 ret = g_dynamic_engine.pefuncs->set_commands((vcp_cmd_h)0);
671                 if (0 != ret) {
672                         SLOG(LOG_WARN, TAG_VCD, "[Engine Agent ERROR] Fail to set command of dynamic engine : error(%d)", ret);
673                         g_dynamic_engine.is_command_ready = false;
674                 } else {
675                         g_dynamic_engine.is_command_ready = true;
676                 }
677
678                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] set command");
679         } else {
680                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Dynamic engine is not available");
681         }
682
683         return 0;
684 }
685
686 int vcd_engine_recognize_start(bool silence)
687 {
688         if (false == g_agent_init) {
689                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
690                 return VCD_ERROR_OPERATION_FAILED;
691         }
692
693         int ret = -1;
694         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] silence is %s", silence ? "true" : "false");
695
696         if (true == g_dynamic_engine.is_loaded && true == g_dynamic_engine.is_command_ready) {
697                 ret = g_dynamic_engine.pefuncs->start(silence);
698                 if (0 != ret) {
699                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] Fail to start engine error(%d)", ret);
700                         return VCD_ERROR_OPERATION_FAILED;
701                 }
702         } else {
703                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Engine is not available (Cannot start)");
704                 return VCD_ERROR_OPERATION_FAILED;
705         }
706
707         SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent SUCCESS] Engine start");
708         return 0;
709 }
710
711 int vcd_engine_recognize_audio(const void* data, unsigned int length, vcp_speech_detect_e* speech_detected)
712 {
713         if (false == g_agent_init) {
714                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
715                 return VCD_ERROR_OPERATION_FAILED;
716         }
717
718         if (NULL == data) {
719                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
720                 return VCD_ERROR_INVALID_PARAMETER;
721         }
722
723         int ret = -1;
724
725         if (true == g_dynamic_engine.is_loaded) {
726                 ret = g_dynamic_engine.pefuncs->set_recording(data, length, speech_detected);
727                 if (0 != ret) {
728                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set recording dynamic engine error(%d)", ret);
729                         if (VCP_ERROR_OUT_OF_NETWORK == ret) {
730                                 return VCD_ERROR_TIMED_OUT;
731                         }
732                         return VCD_ERROR_OPERATION_FAILED;
733                 }
734         }
735
736         return 0;
737 }
738
739 int vcd_engine_recognize_stop()
740 {
741         if (false == g_agent_init) {
742                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
743                 return VCD_ERROR_OPERATION_FAILED;
744         }
745
746         if (true == g_dynamic_engine.is_loaded) {
747                 int ret = -1;
748                 ret = g_dynamic_engine.pefuncs->stop();
749                 if (0 != ret) {
750                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to stop dynamic engine error(%d)", ret);
751                         return VCD_ERROR_OPERATION_FAILED;
752                 }
753         } else {
754                 SLOG(LOG_WARN, TAG_VCD, "[Engine Agent] Dynamic engine is not recording state");
755                 return VCD_ERROR_OPERATION_FAILED;
756         }
757
758         return 0;
759 }
760
761 int vcd_engine_recognize_cancel()
762 {
763         if (false == g_agent_init) {
764                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
765                 return VCD_ERROR_OPERATION_FAILED;
766         }
767
768         int ret = -1;
769         if (true == g_dynamic_engine.is_loaded) {
770                 ret = g_dynamic_engine.pefuncs->cancel();
771                 if (0 != ret) {
772                         SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to cancel dynamic engine error(%d)", ret);
773                 }
774         }
775
776         return 0;
777 }
778
779
780 /*
781 * VCS Engine Interfaces for client and setting
782 */
783
784 int vcd_engine_get_audio_format(const char* audio_id, vcp_audio_type_e* types, int* rate, int* channels)
785 {
786         if (false == g_agent_init) {
787                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
788                 return VCD_ERROR_OPERATION_FAILED;
789         }
790
791         if (true != g_dynamic_engine.is_loaded) {
792                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded");
793         }
794
795         if (NULL == g_dynamic_engine.pefuncs->get_recording_format) {
796                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] The function of engine is NULL!!");
797                 return VCD_ERROR_OPERATION_FAILED;
798         }
799
800         int ret = g_dynamic_engine.pefuncs->get_recording_format(audio_id, types, rate, channels);
801         if (0 != ret) {
802                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] get recording format(%d)", ret);
803                 return VCD_ERROR_OPERATION_FAILED;
804         }
805
806         return 0;
807 }
808
809 bool __supported_language_cb(const char* language, void* user_data)
810 {
811         GList** lang_list = (GList**)user_data;
812
813         if (NULL == language || NULL == lang_list) {
814                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Input parameter is NULL in callback!!!!");
815                 return false;
816         }
817
818         SLOG(LOG_DEBUG, TAG_VCD, "-- Language(%s)", language);
819
820         char* temp_lang = g_strdup(language);
821
822         *lang_list = g_list_append(*lang_list, temp_lang);
823
824         return true;
825 }
826
827 int vcd_engine_supported_langs(GList** lang_list)
828 {
829         if (false == g_agent_init) {
830                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
831                 return VCD_ERROR_OPERATION_FAILED;
832         }
833
834         if (true != g_dynamic_engine.is_loaded) {
835                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded");
836         }
837
838         if (NULL == g_dynamic_engine.pefuncs->foreach_langs) {
839                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] The function of engine is NULL!!");
840                 return VCD_ERROR_OPERATION_FAILED;
841         }
842
843         int ret = g_dynamic_engine.pefuncs->foreach_langs(__supported_language_cb, (void*)lang_list);
844         if (0 != ret) {
845                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] get language list error(%d)", ret);
846                 return VCD_ERROR_OPERATION_FAILED;
847         }
848
849         return 0;
850 }
851
852
853 int vcd_engine_get_current_language(char** lang)
854 {
855         if (false == g_agent_init) {
856                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
857                 return VCD_ERROR_OPERATION_FAILED;
858         }
859
860         if (NULL == lang) {
861                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
862                 return VCD_ERROR_INVALID_PARAMETER;
863         }
864
865         /* get default language */
866         *lang = g_strdup(g_default_lang);
867
868         return 0;
869 }
870
871 int vcd_engine_set_current_language(const char* language)
872 {
873         if (false == g_agent_init) {
874                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
875                 return VCD_ERROR_OPERATION_FAILED;
876         }
877
878         if (NULL == language) {
879                 SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Invalid Parameter");
880                 return VCD_ERROR_INVALID_PARAMETER;
881         }
882
883         int ret;
884
885         if (true == g_dynamic_engine.is_loaded) {
886                 g_dynamic_engine.is_command_ready = false;
887
888                 ret = g_dynamic_engine.pefuncs->set_language(language);
889                 if (0 != ret) {
890                         SLOG(LOG_WARN, TAG_VCD, "[Engine Agent] Fail to set language of dynamic engine error(%d, %s)", ret, language);
891                 }
892         } else {
893                 SLOG(LOG_DEBUG, TAG_VCD, "[Engine Agent] Dynamic engine is not available (Cannot start)");
894         }
895
896         return 0;
897 }
898
899 void __free_language_list(GList* lang_list)
900 {
901         GList *iter = NULL;
902         char* data = NULL;
903
904         /* if list have item */
905         if (g_list_length(lang_list) > 0) {
906                 /* Get a first item */
907                 iter = g_list_first(lang_list);
908
909                 while (NULL != iter) {
910                         data = iter->data;
911
912                         if (NULL != data)
913                                 free(data);
914
915                         lang_list = g_list_remove_link(lang_list, iter);
916
917                         iter = g_list_first(lang_list);
918                 }
919         }
920 }
921
922 int __log_enginelist()
923 {
924         GList *iter = NULL;
925         vcengine_info_s *data = NULL;
926
927         if (0 < g_list_length(g_engine_list)) {
928
929                 /* Get a first item */
930                 iter = g_list_first(g_engine_list);
931
932                 SLOG(LOG_DEBUG, TAG_VCD, "--------------- engine list -------------------");
933
934                 int i = 1;
935                 while (NULL != iter) {
936                         /* Get handle data from list */
937                         data = iter->data;
938
939                         SLOG(LOG_DEBUG, TAG_VCD, "[%dth]", i);
940                         SLOG(LOG_DEBUG, TAG_VCD, "  engine uuid : %s", data->engine_uuid);
941                         SLOG(LOG_DEBUG, TAG_VCD, "  engine name : %s", data->engine_name);
942                         SLOG(LOG_DEBUG, TAG_VCD, "  engine path : %s", data->engine_path);
943                         iter = g_list_next(iter);
944                         i++;
945                 }
946                 SLOG(LOG_DEBUG, TAG_VCD, "----------------------------------------------");
947         } else {
948                 SLOG(LOG_DEBUG, TAG_VCD, "-------------- engine list -------------------");
949                 SLOG(LOG_DEBUG, TAG_VCD, "  No Engine in engine directory");
950                 SLOG(LOG_DEBUG, TAG_VCD, "----------------------------------------------");
951         }
952
953         return 0;
954 }
955
956
957
958