77f7a95c64fa5607cf1616f4f8333b1259b0c44a
[platform/core/uifw/tts.git] / server / ttsd_engine_agent.c
1 /*
2 *  Copyright (c) 2011-2014 Samsung Electronics Co., Ltd All Rights Reserved
3 *  Licensed under the Apache License, Version 2.0 (the "License");
4 *  you may not use this file except in compliance with the License.
5 *  You may obtain a copy of the License at
6 *  http://www.apache.org/licenses/LICENSE-2.0
7 *  Unless required by applicable law or agreed to in writing, software
8 *  distributed under the License is distributed on an "AS IS" BASIS,
9 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 *  See the License for the specific language governing permissions and
11 *  limitations under the License.
12 */
13
14
15 #include <dlfcn.h>
16 #include <dirent.h>
17
18 #include "tts_defs.h"
19 #include "ttsd_main.h"
20 #include "ttsd_engine_agent.h"
21 #include "ttsd_config.h"
22
23 #define ENGINE_PATH_SIZE        256
24
25 /*
26 * Internal data structure
27 */
28 typedef struct {
29         /* base info */
30         char*   engine_uuid;
31         char*   engine_name;
32         char*   engine_path;
33
34         /* info for using engine load */
35         bool    is_set;
36         bool    is_loaded;
37         bool    need_network;
38         void    *handle;
39
40         /* engine base setting */
41         char*   default_lang;
42         int     default_vctype;
43         int     default_speed;
44         int     default_pitch;
45
46         ttspe_funcs_s*  pefuncs;
47         ttspd_funcs_s*  pdfuncs;
48
49         int (*ttsp_load_engine)(const ttspd_funcs_s* pdfuncs, ttspe_funcs_s* pefuncs);
50         int (*ttsp_unload_engine)();
51 } ttsengine_s;
52
53 typedef struct {
54         char*   engine_uuid;
55         char*   engine_path;
56         char*   engine_name;
57         char*   setting_ug_path;
58         bool    use_network;
59 } ttsengine_info_s;
60
61 typedef struct {
62         bool    is_default;
63         bool    is_loaded;
64         int     client_ref_count;
65
66         char*   lang;
67         int     type;
68 } ttsvoice_s;
69
70
71 /** Init flag */
72 static bool g_agent_init;
73
74 /** TTS engine list */
75 static GList *g_engine_list;
76
77 /** Current engine information */
78 static ttsengine_s g_cur_engine;
79
80 /** Current voice information */
81 static GSList* g_cur_voices;
82
83 /** Result callback function */
84 static synth_result_callback g_result_cb;
85
86
87 /** Set current engine */
88 int __internal_set_current_engine(const char* engine_uuid);
89
90 /** Check engine id */
91 int __internal_check_engine_id(const char* engine_uuid);
92
93 /** Update engine list */
94 int __internal_update_engine_list();
95
96 /** Get engine info */
97 int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info);
98
99 /** Callback function for result */
100 bool __result_cb(ttsp_result_event_e event, const void* data, unsigned int data_size, 
101                  ttsp_audio_type_e audio_type, int rate, void *user_data);
102
103 /** Callback function for voice list */
104 bool __supported_voice_cb(const char* language, int type, void* user_data);
105
106 /** Free voice list */
107 void __free_voice_list(GList* voice_list);
108
109 /** Callback function for engine info */
110 void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* setting_ug_name, 
111                       bool use_network, void* user_data);
112
113 /** Callback fucntion for engine setting */
114 bool __engine_setting_cb(const char* key, const char* value, void* user_data);
115
116
117 /** Print list */
118 int ttsd_print_enginelist();
119
120 int ttsd_print_voicelist();
121
122 static const char* __ttsd_get_engine_error_code(ttsp_error_e err)
123 {
124         switch (err) {
125         case TTSP_ERROR_NONE:                   return "TTSP_ERROR_NONE";
126         case TTSP_ERROR_OUT_OF_MEMORY:          return "TTSP_ERROR_OUT_OF_MEMORY";
127         case TTSP_ERROR_IO_ERROR:               return "TTSP_ERROR_IO_ERROR";
128         case TTSP_ERROR_INVALID_PARAMETER:      return "TTSP_ERROR_INVALID_PARAMETER";
129         case TTSP_ERROR_OUT_OF_NETWORK:         return "TTSP_ERROR_OUT_OF_NETWORK";
130         case TTSP_ERROR_INVALID_STATE:          return "TTSP_ERROR_INVALID_STATE";
131         case TTSP_ERROR_INVALID_VOICE:          return "TTSP_ERROR_INVALID_VOICE";
132         case TTSP_ERROR_OPERATION_FAILED:       return "TTSP_ERROR_OPERATION_FAILED";
133         default:
134                 return "Invalid error code";
135         }
136 }
137
138 int ttsd_engine_agent_init(synth_result_callback result_cb)
139 {
140         /* initialize static data */
141         if (result_cb == NULL) {
142                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] invalid parameter");
143                 return TTSD_ERROR_INVALID_PARAMETER;
144         }
145
146         g_result_cb = result_cb;
147
148         g_cur_engine.engine_uuid = NULL;
149         g_cur_engine.engine_name = NULL;
150         g_cur_engine.engine_path = NULL;
151
152         g_cur_engine.is_set = false;
153         g_cur_engine.handle = NULL;
154         g_cur_engine.pefuncs = (ttspe_funcs_s*)calloc(1, sizeof(ttspe_funcs_s));
155         g_cur_engine.pdfuncs = (ttspd_funcs_s*)calloc(1, sizeof(ttspd_funcs_s));
156
157         g_agent_init = true;
158
159         if (0 != ttsd_config_get_default_voice(&(g_cur_engine.default_lang), &(g_cur_engine.default_vctype))) {
160                 SLOG(LOG_WARN, get_tag(), "[Server WARNING] There is No default voice in config");
161                 /* Set default voice */
162                 g_cur_engine.default_lang = strdup(TTS_BASE_LANGUAGE);
163                 g_cur_engine.default_vctype = TTSP_VOICE_TYPE_FEMALE;
164         }
165
166         if (0 != ttsd_config_get_default_speed(&(g_cur_engine.default_speed))) {
167                 SLOG(LOG_WARN, get_tag(), "[Server WARNING] There is No default speed in config");
168                 g_cur_engine.default_speed = TTS_SPEED_NORMAL;
169         }
170
171         if (0 != ttsd_config_get_default_pitch(&(g_cur_engine.default_pitch))) {
172                 SLOG(LOG_WARN, get_tag(), "[Server WARNING] There is No default pitch in config");
173                 g_cur_engine.default_pitch = TTS_PITCH_NORMAL;
174         }
175
176         SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Initialize Engine Agent");
177
178         return 0;
179 }
180
181 int ttsd_engine_agent_release()
182 {
183         if (false == g_agent_init) {
184                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
185                 return TTSD_ERROR_OPERATION_FAILED;
186         }
187
188         /* unload current engine */
189         ttsd_engine_agent_unload_current_engine();
190
191         /* release engine list */
192         GList *iter = NULL;
193         ttsengine_info_s *data = NULL;
194
195         if (g_list_length(g_engine_list) > 0) {
196                 /* Get a first item */
197                 iter = g_list_first(g_engine_list);
198                 while (NULL != iter) {
199                         /* Get data from item */
200                         data = iter->data;
201                         iter = g_list_remove(iter, data);
202
203                         if (NULL != data) {
204                                 if (NULL != data->engine_uuid)          free(data->engine_uuid);
205                                 if (NULL != data->engine_name)          free(data->engine_name);
206                                 if (NULL != data->setting_ug_path)      free(data->setting_ug_path);
207                                 if (NULL != data->engine_path)          free(data->engine_path);
208                                 free(data);
209                         }
210                 }
211         }
212         g_list_free(iter);
213
214         /* release current engine data */
215         if (g_cur_engine.engine_uuid != NULL)   free(g_cur_engine.engine_uuid);
216         if (g_cur_engine.engine_name != NULL)   free(g_cur_engine.engine_name);
217         if (g_cur_engine.engine_path != NULL)   free(g_cur_engine.engine_path);
218
219         if (g_cur_engine.pefuncs != NULL)       free(g_cur_engine.pefuncs);
220         if (g_cur_engine.pdfuncs != NULL)       free(g_cur_engine.pdfuncs);
221         if (g_cur_engine.default_lang != NULL)  free(g_cur_engine.default_lang);
222         g_result_cb = NULL;
223         g_agent_init = false;
224
225         SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Release Engine Agent");
226
227         return 0;
228 }
229
230 int ttsd_engine_agent_initialize_current_engine()
231 {
232         if (false == g_agent_init) {
233                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
234                 return TTSD_ERROR_OPERATION_FAILED;
235         }
236
237         /* update engine list */
238         if (0 != __internal_update_engine_list()) {
239                 SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] No engine error");
240                 return TTSD_ERROR_OPERATION_FAILED;
241         }
242
243         /* 2. get current engine from config */
244         char* cur_engine_uuid = NULL;
245         bool is_get_engineid_from_config = false;
246
247         if (0 != ttsd_config_get_default_engine(&cur_engine_uuid)) {
248                 /*not set current engine */
249                 /*set system default engine*/
250                 GList *iter = NULL;
251                 ttsengine_info_s *data = NULL;
252
253                 if (g_list_length(g_engine_list) > 0) {
254                         iter = g_list_first(g_engine_list);
255                         data = iter->data;
256
257                         if (NULL != data) {
258                                 if (NULL != data->engine_uuid) {
259                                         cur_engine_uuid = strdup(data->engine_uuid);
260                                         ttsd_config_set_default_engine(cur_engine_uuid);
261                                 } else {
262                                         SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Data of current engine is corrupt");
263                                         return TTSD_ERROR_OPERATION_FAILED;
264                                 }
265                         }
266                 } else {
267                         SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] Fail to set a engine of engine list");
268                         return TTSD_ERROR_OPERATION_FAILED;
269                 }
270
271                 is_get_engineid_from_config = false;
272         } else {
273                 is_get_engineid_from_config = true;
274         }
275
276         if (NULL == cur_engine_uuid) {
277                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Current engine id is NULL");
278                 return TTSD_ERROR_OPERATION_FAILED;
279         }
280
281         /* check whether cur engine uuid is valid or not. */
282         if (0 != __internal_check_engine_id(cur_engine_uuid)) {
283                 SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] It is not valid engine id from config");
284
285                 GList *iter = NULL;
286
287                 if (g_list_length(g_engine_list) > 0)
288                         iter = g_list_first(g_engine_list);
289                 else {
290                         SLOG(LOG_WARN, get_tag(), "[Engine Agent ERROR] NO TTS Engine !!");
291                         if (NULL != cur_engine_uuid)    free(cur_engine_uuid);
292                         return TTSD_ERROR_OPERATION_FAILED;
293                 }
294
295                 if (cur_engine_uuid != NULL)    free(cur_engine_uuid);
296                 ttsengine_info_s *data = NULL;
297                 data = iter->data;
298
299                 cur_engine_uuid = strdup(data->engine_uuid);
300
301                 is_get_engineid_from_config = false;
302         }
303
304         if (NULL != cur_engine_uuid)
305                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Current Engine Id : %s", cur_engine_uuid);
306         else
307                 return TTSD_ERROR_OPERATION_FAILED;
308
309         /* set current engine */
310         if (0 != __internal_set_current_engine(cur_engine_uuid)) {
311                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to set current engine ");
312                 if (NULL != cur_engine_uuid)    free(cur_engine_uuid);
313                 return TTSD_ERROR_OPERATION_FAILED;
314         }
315
316         if (false == is_get_engineid_from_config) {
317                 if (0 != ttsd_config_set_default_engine(cur_engine_uuid)) {
318                         SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to set id to config");
319                 }
320         }
321
322         if (NULL != cur_engine_uuid)    free(cur_engine_uuid);
323
324         SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Set current engine");
325
326         return 0;
327 }
328
329 int __internal_check_engine_id(const char* engine_uuid)
330 {
331         GList *iter = NULL;
332         ttsengine_s *data = NULL;
333
334         if (g_list_length(g_engine_list) > 0) {
335                 iter = g_list_first(g_engine_list);
336
337                 while (NULL != iter) {
338                         data = iter->data;
339
340                         if (0 == strncmp(engine_uuid, data->engine_uuid, strlen(data->engine_uuid)))
341                                 return 0;
342
343                         iter = g_list_next(iter);
344                 }
345         }
346
347         return -1;
348 }
349
350 void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* setting_ug_name, 
351                              bool use_network, void* user_data)
352 {
353         ttsengine_info_s* temp = (ttsengine_info_s*)user_data;
354
355         if (NULL != engine_uuid)
356                 temp->engine_uuid = strdup(engine_uuid);
357
358         if (NULL != engine_name)
359                 temp->engine_name = strdup(engine_name);
360
361         if (NULL != setting_ug_name)
362                 temp->setting_ug_path = strdup(setting_ug_name);
363
364         temp->use_network = use_network;
365         return;
366 }
367
368 int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info)
369 {
370         char *error;
371         void* handle;
372
373         handle = dlopen(filepath, RTLD_LAZY);
374
375         if (!handle) {
376                 SECURE_SLOG(LOG_WARN, get_tag(), "[Engine Agent] Invalid engine : %s", filepath);
377                 return TTSD_ERROR_OPERATION_FAILED;
378         }
379
380         /* link engine to daemon */
381         dlsym(handle, "ttsp_load_engine");
382         if ((error = dlerror()) != NULL) {
383                 SECURE_SLOG(LOG_WARN, get_tag(), "[Engine Agent] Fail to open ttsp_load_engine : path(%s) message(%s)", filepath, error);
384                 dlclose(handle);
385                 return TTSD_ERROR_OPERATION_FAILED;
386         }
387
388         dlsym(handle, "ttsp_unload_engine");
389         if ((error = dlerror()) != NULL) {
390                 SECURE_SLOG(LOG_WARN, get_tag(), "[Engine Agent] Fail to open ttsp_unload_engine : path(%s) message(%s)", filepath, error);
391                 dlclose(handle);
392                 return TTSD_ERROR_OPERATION_FAILED;
393         }
394
395         int (*get_engine_info)(ttsp_engine_info_cb callback, void* user_data);
396
397         get_engine_info = (int (*)(ttsp_engine_info_cb, void*))dlsym(handle, "ttsp_get_engine_info");
398         if (NULL != (error = dlerror()) || NULL == get_engine_info) {
399                 SLOG(LOG_WARN, get_tag(), "[Engine Agent] Fail to open ttsp_get_engine_info() :path(%s) message(%s)", filepath, error);
400                 dlclose(handle);
401                 return TTSD_ERROR_OPERATION_FAILED;
402         }
403
404         ttsengine_info_s* temp;
405         temp = (ttsengine_info_s*)calloc(1, sizeof(ttsengine_info_s));
406         if (NULL == temp) {
407                 SLOG(LOG_WARN, get_tag(), "[Engine Agent] Fail to alloc memory");
408                 dlclose(handle);
409                 return TTSD_ERROR_OUT_OF_MEMORY;
410         }
411
412         /* get engine info */
413         if (0 != get_engine_info(&__engine_info_cb, (void*)temp)) {
414                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to get engine info");
415                 dlclose(handle);
416                 free(temp);
417                 return TTSD_ERROR_OPERATION_FAILED;
418         }
419
420         /* close engine */
421         dlclose(handle);
422
423         if (TTSD_MODE_SCREEN_READER == ttsd_get_mode() && true == temp->use_network) {
424                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent WARNING] %s is invalid because of network based", temp->engine_name);
425                 if (NULL != temp->engine_uuid)          free(temp->engine_uuid);
426                 if (NULL != temp->engine_name)          free(temp->engine_name);
427                 if (NULL != temp->setting_ug_path)      free(temp->setting_ug_path);
428                 free(temp);
429                 return TTSD_ERROR_OPERATION_FAILED;
430         }
431
432         temp->engine_path = strdup(filepath);
433
434         SLOG(LOG_DEBUG, get_tag(), "----- Valid engine");
435         SECURE_SLOG(LOG_DEBUG, get_tag(), "Engine uuid : %s", temp->engine_uuid);
436         SECURE_SLOG(LOG_DEBUG, get_tag(), "Engine name : %s", temp->engine_name);
437         SECURE_SLOG(LOG_DEBUG, get_tag(), "Setting path : %s", temp->setting_ug_path);
438         SECURE_SLOG(LOG_DEBUG, get_tag(), "Engine path : %s", temp->engine_path);
439         SECURE_SLOG(LOG_DEBUG, get_tag(), "Use network : %s", temp->use_network ? "true" : "false");
440         SLOG(LOG_DEBUG, get_tag(), "-----");
441         SLOG(LOG_DEBUG, get_tag(), "  ");
442
443         *info = temp;
444
445         return 0;
446 }
447
448 int __internal_update_engine_list()
449 {
450         /* relsease engine list */
451         GList *iter = NULL;
452         ttsengine_info_s *data = NULL;
453
454         if (g_list_length(g_engine_list) > 0) {
455                 iter = g_list_first(g_engine_list);
456
457                 while (NULL != iter) {
458                         data = iter->data;
459
460                         if (data != NULL)       free(data);
461                         g_engine_list = g_list_remove_link(g_engine_list, iter);
462                         iter = g_list_first(g_engine_list);
463                 }
464         }
465
466         /* get file name from engine directory and get engine information from each filename */
467         DIR *dp;
468         struct dirent *dirp;
469         dp = opendir(TTS_DEFAULT_ENGINE);
470
471         if (dp != NULL) {
472                 while ((dirp = readdir(dp)) != NULL) {
473                         ttsengine_info_s* info;
474                         char* filepath = NULL;
475                         int file_size;
476
477                         file_size = strlen(TTS_DEFAULT_ENGINE) + strlen(dirp->d_name) + 5;
478                         filepath = (char*)calloc(file_size, sizeof(char));
479
480                         if (NULL != filepath) {
481                                 snprintf(filepath, file_size, "%s/%s", TTS_DEFAULT_ENGINE, dirp->d_name);
482                         } else {
483                                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not enough memory!!");
484                                 continue;
485                         }
486
487                         /* get its info and update engine list */
488                         if (0 == __internal_get_engine_info(filepath, &info)) {
489                                 /* add engine info to g_engine_list */
490                                 g_engine_list = g_list_append(g_engine_list, info);
491                         }
492
493                         if (NULL != filepath)   free(filepath);
494                 }
495
496                 closedir(dp);
497         }
498
499         dp = opendir(TTS_DOWNLOAD_ENGINE);
500
501         if (dp != NULL) {
502                 while ((dirp = readdir(dp)) != NULL) {
503                         ttsengine_info_s* info;
504                         char* filepath = NULL;
505                         int file_size;
506
507                         file_size = strlen(TTS_DOWNLOAD_ENGINE) + strlen(dirp->d_name) + 5;
508                         filepath = (char*)calloc(file_size, sizeof(char));
509
510                         if (NULL != filepath) {
511                                 snprintf(filepath, file_size, "%s/%s", TTS_DOWNLOAD_ENGINE, dirp->d_name);
512                         } else {
513                                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not enough memory!!");
514                                 continue;
515                         }
516
517                         /* get its info and update engine list */
518                         if (0 == __internal_get_engine_info(filepath, &info)) {
519                                 /* add engine info to g_engine_list */
520                                 g_engine_list = g_list_append(g_engine_list, info);
521                         }
522
523                         if (NULL != filepath)   free(filepath);
524                 }
525
526                 closedir(dp);
527         }
528
529         if (g_list_length(g_engine_list) <= 0) {
530                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] No Engine");
531                 return TTSD_ERROR_OPERATION_FAILED;
532         }
533
534 #ifdef ENGINE_AGENT_DEBUG
535         ttsd_print_enginelist();
536 #endif
537         return 0;
538 }
539
540 int __internal_set_current_engine(const char* engine_uuid)
541 {
542         /* check whether engine id is valid or not. */
543         GList *iter = NULL;
544         ttsengine_info_s *data = NULL;
545
546         bool flag = false;
547         if (g_list_length(g_engine_list) > 0) {
548                 iter = g_list_first(g_engine_list);
549
550                 while (NULL != iter) {
551                         data = iter->data;
552
553                         if (0 == strncmp(data->engine_uuid, engine_uuid, strlen(engine_uuid))) {
554                                 flag = true;
555                                 break;
556                         }
557
558                         /*Get next item*/
559                         iter = g_list_next(iter);
560                 }
561         }
562
563         /* If current engine does not exist, return error */
564         if (false == flag) {
565                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Cannot find engine id");
566                 return TTSD_ERROR_OPERATION_FAILED;
567         } else {
568                 if (g_cur_engine.engine_uuid != NULL) {
569                         /*compare current engine uuid */
570                         if (0 == strncmp(g_cur_engine.engine_uuid, data->engine_uuid, strlen(engine_uuid))) {
571                                 SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] tts engine has already been set");
572                                 return 0;
573                         }
574                 }
575         }
576
577         /* set data from g_engine_list */
578         if (g_cur_engine.engine_uuid != NULL)   free(g_cur_engine.engine_uuid);
579         if (g_cur_engine.engine_name != NULL)   free(g_cur_engine.engine_name);
580         if (g_cur_engine.engine_path != NULL)   free(g_cur_engine.engine_path);
581
582         if (NULL == data->engine_uuid || NULL == data->engine_name || NULL == data->engine_path) {
583                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Engine data is NULL");
584                 return TTSD_ERROR_OPERATION_FAILED;
585         }
586
587         g_cur_engine.engine_uuid = strdup(data->engine_uuid);
588         g_cur_engine.engine_name = strdup(data->engine_name);
589         g_cur_engine.engine_path = strdup(data->engine_path);
590
591         g_cur_engine.handle = NULL;
592         g_cur_engine.is_loaded = false;
593         g_cur_engine.is_set = true;
594         g_cur_engine.need_network = data->use_network;
595
596         SLOG(LOG_DEBUG, get_tag(), "-----");
597         SECURE_SLOG(LOG_DEBUG, get_tag(), "Current engine uuid : %s", g_cur_engine.engine_uuid);
598         SECURE_SLOG(LOG_DEBUG, get_tag(), "Current engine name : %s", g_cur_engine.engine_name);
599         SECURE_SLOG(LOG_DEBUG, get_tag(), "Current engine path : %s", g_cur_engine.engine_path);
600         SLOG(LOG_DEBUG, get_tag(), "-----");
601
602         return 0;
603 }
604
605 bool __set_voice_info_cb(const char* language, int type, void* user_data)
606 {
607         if (NULL == language) {
608                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!");
609                 return false;
610         }
611
612         ttsvoice_s* voice = calloc(1, sizeof(ttsvoice_s));
613         voice->lang = strdup(language);
614         voice->type = type;
615
616         voice->client_ref_count = 0;
617         voice->is_loaded = false;
618
619         if (0 == strcmp(g_cur_engine.default_lang, language) && g_cur_engine.default_vctype == type) {
620                 voice->is_default = true;
621                 voice->is_loaded = true;
622         } else {
623                 voice->is_default = false;
624         }
625
626         g_cur_voices = g_slist_append(g_cur_voices, voice);
627
628         return true;
629 }
630
631 int __update_voice_list()
632 {
633         /* Get voice list */
634         g_cur_voices = NULL;
635         int ret = 0;
636
637         ret = g_cur_engine.pefuncs->foreach_voices(__set_voice_info_cb, NULL);
638         if (0 != ret || 0 >= g_slist_length(g_cur_voices)) {
639                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to get voice list : result(%d)", ret);
640                 return -1;
641         }
642
643 #ifdef ENGINE_AGENT_DEBUG
644         ttsd_print_voicelist();
645 #endif
646         return 0;
647 }
648
649 int ttsd_engine_agent_load_current_engine()
650 {
651         if (false == g_agent_init) {
652                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
653                 return TTSD_ERROR_OPERATION_FAILED;
654         }
655
656         if (false == g_cur_engine.is_set) {
657                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] No Current Engine ");
658                 return TTSD_ERROR_OPERATION_FAILED;
659         }
660
661         /* check whether current engine is loaded or not */
662         if (true == g_cur_engine.is_loaded) {
663                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent] Engine has already been loaded ");
664                 return 0;
665         }
666
667         /* open engine */
668         char *error = NULL;
669         g_cur_engine.handle = dlopen(g_cur_engine.engine_path, RTLD_LAZY); /* RTLD_LAZY RTLD_NOW*/
670
671         if (NULL != (error = dlerror()) || NULL == g_cur_engine.handle) {
672                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to get current engine handle : %s", error);
673                 return -2;
674         }
675
676         g_cur_engine.ttsp_unload_engine = (int (*)())dlsym(g_cur_engine.handle, "ttsp_unload_engine");
677         if (NULL != (error = dlerror()) || NULL == g_cur_engine.ttsp_unload_engine) {
678                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to link daemon to ttsp_unload_engine() : %s", error);
679                 return -3;
680         }
681
682         g_cur_engine.ttsp_load_engine = (int (*)(const ttspd_funcs_s* , ttspe_funcs_s*))dlsym(g_cur_engine.handle, "ttsp_load_engine");
683         if (NULL != (error = dlerror()) || NULL == g_cur_engine.ttsp_load_engine) {
684                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to link daemon to ttsp_load_engine() : %s", error);
685                 return -3;
686         }
687
688         /* load engine */
689         g_cur_engine.pdfuncs->version = 1;
690         g_cur_engine.pdfuncs->size = sizeof(ttspd_funcs_s);
691
692         int ret = 0;
693         ret = g_cur_engine.ttsp_load_engine(g_cur_engine.pdfuncs, g_cur_engine.pefuncs);
694         if (0 != ret) {
695                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to load engine - %s : result(%s)",
696                          g_cur_engine.engine_path, __ttsd_get_engine_error_code(ret));
697                 return TTSD_ERROR_OPERATION_FAILED;
698         }
699
700         /* engine error check */
701         if (g_cur_engine.pefuncs->size != sizeof(ttspe_funcs_s)) {
702                 SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] The size of engine function is not valid");
703         }
704
705         if (NULL == g_cur_engine.pefuncs->initialize ||
706                 NULL == g_cur_engine.pefuncs->deinitialize ||
707                 NULL == g_cur_engine.pefuncs->foreach_voices ||
708                 NULL == g_cur_engine.pefuncs->is_valid_voice ||
709                 NULL == g_cur_engine.pefuncs->start_synth ||
710                 NULL == g_cur_engine.pefuncs->cancel_synth) {
711                 SLOG(LOG_ERROR, get_tag(), "[Engine ERROR] The engine functions are NOT valid");
712                 return TTSD_ERROR_OPERATION_FAILED;
713         }
714
715         ret = g_cur_engine.pefuncs->initialize(__result_cb);
716         if (0 != ret) {
717                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to initialize current engine : %s", __ttsd_get_engine_error_code(ret));
718                 return TTSD_ERROR_OPERATION_FAILED;
719         }
720
721         /* Get voice info of current engine */
722         ret = __update_voice_list();
723         if (0 != ret) {
724                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to set voice info : result(%d)", ret);
725                 return TTSD_ERROR_OPERATION_FAILED;
726         }
727
728         /* Select default voice */
729         if (NULL != g_cur_engine.default_lang) {
730                 if (true == g_cur_engine.pefuncs->is_valid_voice(g_cur_engine.default_lang, g_cur_engine.default_vctype)) {
731                         SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Set origin default voice to current engine : lang(%s), type(%d)",
732                                  g_cur_engine.default_lang,  g_cur_engine.default_vctype);
733                 } else {
734                         SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] Fail set origin default voice : lang(%s), type(%d)",
735                                  g_cur_engine.default_lang, g_cur_engine.default_vctype);
736
737                         return TTSD_ERROR_OPERATION_FAILED;
738                 }
739         }
740
741         /* load default voice */
742         if (NULL != g_cur_engine.pefuncs->load_voice) {
743                 ret = g_cur_engine.pefuncs->load_voice(g_cur_engine.default_lang, g_cur_engine.default_vctype);
744                 if (0 == ret) {
745                         SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Load default voice : lang(%s), type(%d)",
746                                  g_cur_engine.default_lang,  g_cur_engine.default_vctype);
747                 } else {
748                         SLOG(LOG_WARN, get_tag(), "[Engine Agent ERROR] Fail to load default voice : lang(%s), type(%d) result(%s)",
749                                  g_cur_engine.default_lang, g_cur_engine.default_vctype, __ttsd_get_engine_error_code(ret));
750
751                         return TTSD_ERROR_OPERATION_FAILED;
752                 }
753         }
754
755 #if 0
756         if (false == set_voice) {
757                 /* get language list */
758                 int ret;
759                 GList* voice_list = NULL;
760
761                 ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, &voice_list);
762
763                 if (0 == ret && 0 < g_list_length(voice_list)) {
764                         GList *iter = NULL;
765                         voice_s* voice = NULL;
766
767                         iter = g_list_first(voice_list);
768
769                         /* check english */
770                         while (NULL != iter) {
771                                 voice = iter->data;
772
773                                 if (NULL != voice) {
774                                         if (0 == strcmp("en_US", voice->language))
775                                                 break;
776                                 }
777
778                                 iter = g_list_next(iter);
779                         }
780                         if (NULL == voice) {
781                                 SLOG(LOG_ERROR, get_tag(), "[Engine ERROR] Fail to find voice in list");
782                                 return TTSD_ERROR_OPERATION_FAILED;
783                         }
784
785                         /* Set selected language and type */
786                         if (true != g_cur_engine.pefuncs->is_valid_voice(voice->language, voice->type)) {
787                                 SLOG(LOG_ERROR, get_tag(), "[Engine ERROR] Fail voice is NOT valid");
788                                 return TTSD_ERROR_OPERATION_FAILED;
789                         }
790
791                         ttsd_config_set_default_voice(voice->language, (int)voice->type);
792
793                         g_cur_engine.default_lang = strdup(voice->language);
794                         g_cur_engine.default_vctype = voice->type;
795
796                         SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Select default voice : lang(%s), type(%d)",
797                                  voice->language,  voice->type);
798
799                         __free_voice_list(voice_list);
800                 } else {
801                         SLOG(LOG_ERROR, get_tag(), "[Engine ERROR] Fail to get language list : result(%d)", ret);
802                         return TTSD_ERROR_OPERATION_FAILED;
803                 }
804         }
805 #endif
806         g_cur_engine.is_loaded = true;
807
808         return 0;
809 }
810
811 int ttsd_engine_agent_unload_current_engine()
812 {
813         if (false == g_agent_init) {
814                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
815                 return TTSD_ERROR_OPERATION_FAILED;
816         }
817
818         if (false == g_cur_engine.is_set) {
819                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] No Current Engine ");
820                 return TTSD_ERROR_OPERATION_FAILED;
821         }
822
823         if (false == g_cur_engine.is_loaded) {
824                 SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Engine has already been unloaded ");
825                 return 0;
826         }
827
828         /* shutdown engine */
829         int ret = 0;
830         ret = g_cur_engine.pefuncs->deinitialize();
831         if (0 != ret) {
832                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent] Fail deinitialize() : %s", __ttsd_get_engine_error_code(ret));
833         }
834
835         /* unload engine */
836         g_cur_engine.ttsp_unload_engine();
837
838         dlclose(g_cur_engine.handle);
839
840         /* reset current engine data */
841         g_cur_engine.handle = NULL;
842         g_cur_engine.is_loaded = false;
843
844         GSList *iter = NULL;
845         ttsvoice_s* data = NULL;
846
847         iter = g_slist_nth(g_cur_voices, 0);
848         while (NULL != iter) {
849                 data = iter->data;
850
851                 if (NULL != data) {
852                         if (NULL != data->lang)         free(data->lang);
853                         g_cur_voices = g_slist_remove(g_cur_voices, data);
854                         free(data);
855                         data = NULL;
856                 }
857
858                 iter = g_slist_nth(g_cur_voices, 0);
859         }
860
861         return 0;
862 }
863
864 bool ttsd_engine_agent_need_network()
865 {
866         if (false == g_agent_init) {
867                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
868                 return TTSD_ERROR_OPERATION_FAILED;
869         }
870
871         if (false == g_cur_engine.is_loaded) {
872                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
873                 return TTSD_ERROR_OPERATION_FAILED;
874         }
875
876         return g_cur_engine.need_network;
877 }
878
879 bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang, int* out_type)
880 {
881         if (NULL == lang || NULL == out_lang || NULL == out_type) {
882                 return false;
883         }
884
885         if (false == g_cur_engine.is_loaded) {
886                 SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] Not loaded engine");
887                 return false;
888         }
889
890         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Select voice : input lang(%s), input type(%d), default lang(%s), default type(%d)", 
891                 lang, type, g_cur_engine.default_lang, g_cur_engine.default_vctype);
892
893         /* case 1 : Both are default */
894         if (0 == strncmp(lang, "default", strlen("default")) && 0 == type) {
895                 *out_lang = strdup(g_cur_engine.default_lang);
896                 *out_type = g_cur_engine.default_vctype;
897                 return true;
898         }
899
900         /* Get voice list */
901         GList* voice_list = NULL;
902         int ret = 0;
903
904         ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, &voice_list);
905         if (0 != ret || 0 >= g_list_length(voice_list)) {
906                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to get voice list : result(%d)", ret);
907                 return false;
908         }
909
910         bool result;
911         result = false;
912
913         GList *iter = NULL;
914         voice_s* voice;
915
916         /* lang and type are not default type */
917         if (0 != strncmp(lang, "default", strlen("default")) && 0 != type) {
918                 iter = g_list_first(voice_list);
919
920                 while (NULL != iter) {
921                         /* Get handle data from list */
922                         voice = iter->data;
923
924                         if (0 == strncmp(voice->language, lang, strlen(lang)) &&  voice->type == type) {
925                                 *out_lang = strdup(voice->language);
926                                 *out_type = voice->type;
927                                 result = true;
928                                 break;
929                         }
930
931                         iter = g_list_next(iter);
932                 }
933
934         } else if (0 != strncmp(lang, "default", strlen("default")) && 0 == type) {
935                 /* Only type is default */
936                 if (0 == strncmp(lang, g_cur_engine.default_lang, strlen(g_cur_engine.default_lang))) {
937                         *out_lang = strdup(g_cur_engine.default_lang);
938                         *out_type = g_cur_engine.default_vctype;
939                         result = true;
940                 } else {
941                         voice_s* voice_selected = NULL;
942                         iter = g_list_first(voice_list);
943                         while (NULL != iter) {
944                                 /* Get handle data from list */
945                                 voice = iter->data;
946
947                                 if (0 == strncmp(voice->language, lang, strlen(lang))) {
948                                         voice_selected = voice;
949                                         if (voice->type == g_cur_engine.default_vctype) {
950                                                 voice_selected = voice;
951                                                 break;
952                                         }
953                                 }
954                                 iter = g_list_next(iter);
955                         }
956
957                         if (NULL != voice_selected) {
958                                 *out_lang = strdup(voice_selected->language);
959                                 *out_type = voice_selected->type;
960                                 result = true;
961                         }
962                 }
963         } else if (0 == strncmp(lang, "default", strlen("default")) && 0 != type) {
964                 /* Only lang is default */
965                 if (type == g_cur_engine.default_vctype) {
966                         *out_lang = strdup(g_cur_engine.default_lang);
967                         *out_type = g_cur_engine.default_vctype;
968                         result = true;
969                 } else {
970                         voice_s* voice_selected = NULL;
971                         iter = g_list_first(voice_list);
972                         while (NULL != iter) {
973                                 /* Get handle data from list */
974                                 voice = iter->data;
975
976                                 if (0 == strncmp(voice->language, g_cur_engine.default_lang, strlen(g_cur_engine.default_lang))) {
977                                         voice_selected = voice;
978                                         if (voice->type == type) {
979                                                 voice_selected = voice;
980                                                 break;
981                                         }
982                                 }
983                                 iter = g_list_next(iter);
984                         }
985
986                         if (NULL != voice_selected) {
987                                 *out_lang = strdup(voice->language);
988                                 *out_type = voice_selected->type;
989                                 result = true;
990                         }
991                 }
992         }
993
994         if (true == result) {
995                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Selected voice : lang(%s), type(%d)", *out_lang, *out_type);
996         }
997
998         __free_voice_list(voice_list);
999
1000         return result;
1001 }
1002
1003 bool ttsd_engine_agent_is_same_engine(const char* engine_id)
1004 {
1005         if (false == g_agent_init) {
1006                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
1007                 return false;
1008         }
1009
1010         if (false == g_cur_engine.is_loaded) {
1011                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1012                 return false;
1013         }
1014
1015         /* compare current engine and engine id.*/
1016         if (0 == strncmp(g_cur_engine.engine_uuid, engine_id, strlen(engine_id))) {
1017                 return true;
1018         }
1019
1020         return false;
1021 }
1022
1023 int ttsd_engine_agent_set_default_engine(const char* engine_id)
1024 {
1025         if (false == g_agent_init) {
1026                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
1027                 return TTSD_ERROR_OPERATION_FAILED;
1028         }
1029
1030         /* compare current engine and new engine.*/
1031         if (0 == strncmp(g_cur_engine.engine_uuid, engine_id, strlen(engine_id))) {
1032                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] new engine(%s) is the same as current engine", engine_id);
1033                 return 0;
1034         }
1035
1036         bool is_engine_loaded = false;
1037         char* tmp_uuid = NULL;
1038         tmp_uuid = strdup(g_cur_engine.engine_uuid);
1039         if (NULL == tmp_uuid) {
1040                         SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Current engine id is NULL");
1041                         return TTSD_ERROR_OPERATION_FAILED;
1042         }
1043
1044         is_engine_loaded = g_cur_engine.is_loaded;
1045
1046         if (true == is_engine_loaded) {
1047                 /* unload engine */
1048                 if (0 != ttsd_engine_agent_unload_current_engine()) {
1049                         SLOG(LOG_ERROR, get_tag(), "[Engine Agent Error] fail to unload current engine");
1050                 }
1051         }
1052
1053         /* change current engine */
1054         if (0 != __internal_set_current_engine(engine_id)) {
1055                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to set current engine. Recovery origin engine");
1056
1057                 /* roll back to old current engine. */
1058                 __internal_set_current_engine(tmp_uuid);
1059                 if (true == is_engine_loaded) {
1060                         ttsd_engine_agent_load_current_engine();
1061                 }
1062
1063                 if (tmp_uuid != NULL)   free(tmp_uuid);
1064                 return TTSD_ERROR_OPERATION_FAILED;
1065         }
1066
1067         if (true == is_engine_loaded) {
1068                 /* load engine */
1069                 if (0 != ttsd_engine_agent_load_current_engine()) {
1070                         SLOG(LOG_ERROR, get_tag(), "[Engine Agent Error] Fail to load new engine. Recovery origin engine");
1071
1072                         /* roll back to old current engine. */
1073                         __internal_set_current_engine(tmp_uuid);
1074                         if (true == is_engine_loaded) {
1075                                 ttsd_engine_agent_load_current_engine();
1076                         }
1077
1078                         if (tmp_uuid != NULL)   free(tmp_uuid);
1079                         return TTSD_ERROR_OPERATION_FAILED;
1080                 } else {
1081                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] load new engine : %s", engine_id);
1082                 }
1083         }
1084
1085         if (tmp_uuid != NULL)   free(tmp_uuid);
1086         return 0;
1087 }
1088
1089 int ttsd_engine_agent_set_default_voice(const char* language, int vctype)
1090 {
1091         if (false == g_agent_init) {
1092                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
1093                 return TTSD_ERROR_OPERATION_FAILED;
1094         }
1095
1096         if (false == g_cur_engine.is_loaded) {
1097                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1098                 return TTSD_ERROR_OPERATION_FAILED;
1099         }
1100
1101         if (false == g_cur_engine.pefuncs->is_valid_voice(language, vctype)) {
1102                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Voice is NOT valid !!");
1103                 return TTSD_ERROR_INVALID_VOICE;
1104         }
1105
1106         int ret = -1;
1107         GSList *iter = NULL;
1108         ttsvoice_s* data = NULL;
1109
1110         /* Update new default voice info */
1111         iter = g_slist_nth(g_cur_voices, 0);
1112         while (NULL != iter) {
1113                 /* Get handle data from list */
1114                 data = iter->data;
1115
1116                 if (NULL == data) {
1117                         SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Voice data is NULL");
1118                         return TTSD_ERROR_OPERATION_FAILED;
1119                 }
1120
1121                 if (0 == strcmp(data->lang, language) && data->type == vctype) {
1122                         data->is_default = true;
1123                         if (0 == data->client_ref_count) {
1124                                 /* load voice */
1125                                 if (NULL != g_cur_engine.pefuncs->load_voice) {
1126                                         ret = g_cur_engine.pefuncs->load_voice(data->lang, data->type);
1127                                         if (0 == ret) {
1128                                                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] load voice : lang(%s), type(%d)", 
1129                                                         data->lang, data->type);
1130                                                 data->is_loaded = true;
1131                                         } else {
1132                                                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to load voice : lang(%s), type(%d), result(%s)",
1133                                                         data->lang, data->type, __ttsd_get_engine_error_code(ret));
1134                                         }
1135                                 } else {
1136                                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent ERROR] Load voice of engine function is NULL");
1137                                 }
1138                         }
1139                         break;
1140                 }
1141
1142                 /*Get next item*/
1143                 iter = g_slist_next(iter);
1144         }
1145
1146 #ifdef ENGINE_AGENT_DEBUG
1147         ttsd_print_voicelist();
1148 #endif
1149
1150         /* Update old default voice info */
1151         iter = g_slist_nth(g_cur_voices, 0);
1152         while (NULL != iter) {
1153                 /*Get handle data from list*/
1154                 data = iter->data;
1155
1156                 if (NULL == data) {
1157                         SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Voice data is NULL");
1158                         return TTSD_ERROR_OPERATION_FAILED;
1159                 }
1160
1161                 if (0 == strcmp(data->lang, g_cur_engine.default_lang) && data->type == g_cur_engine.default_vctype) {
1162                         data->is_default = false;
1163                         if (0 == data->client_ref_count) {
1164                                 /* Unload voice */
1165                                 if (NULL != g_cur_engine.pefuncs->unload_voice) {
1166                                         ret = g_cur_engine.pefuncs->unload_voice(data->lang, data->type);
1167                                         if (0 == ret) {
1168                                                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Unload voice : lang(%s), type(%d)", 
1169                                                         data->lang, data->type);
1170                                                 data->is_loaded = false;
1171                                         } else {
1172                                                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to unload voice : lang(%s), type(%d), result(%s)",
1173                                                         data->lang, data->type, __ttsd_get_engine_error_code(ret));
1174                                         }
1175                                 } else {
1176                                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent ERROR] Unload voice of engine function is NULL");
1177                                 }
1178                         }
1179                         break;
1180                 }
1181
1182                 /*Get next item*/
1183                 iter = g_slist_next(iter);
1184         }
1185
1186         if (NULL != g_cur_engine.default_lang)  free(g_cur_engine.default_lang);
1187
1188         g_cur_engine.default_lang = strdup(language);
1189         g_cur_engine.default_vctype = vctype;
1190
1191 #ifdef ENGINE_AGENT_DEBUG
1192         ttsd_print_voicelist();
1193 #endif
1194
1195         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Set default voice : lang(%s), type(%d)",
1196                 g_cur_engine.default_lang, g_cur_engine.default_vctype);
1197
1198         return 0;
1199 }
1200
1201 int ttsd_engine_agent_set_default_speed(int speed)
1202 {
1203         if (false == g_agent_init) {
1204                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
1205                 return TTSD_ERROR_OPERATION_FAILED;
1206         }
1207
1208         g_cur_engine.default_speed = speed;
1209
1210         return 0;
1211 }
1212
1213 int ttsd_engine_agent_set_default_pitch(int pitch)
1214 {
1215         if (false == g_agent_init) {
1216                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
1217                 return TTSD_ERROR_OPERATION_FAILED;
1218         }
1219
1220         if (false == g_cur_engine.is_loaded) {
1221                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1222                 return TTSD_ERROR_OPERATION_FAILED;
1223         }
1224
1225         if (NULL == g_cur_engine.pefuncs->set_pitch) {
1226                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not support pitch");
1227                 return TTSD_ERROR_OPERATION_FAILED;
1228         }
1229
1230         int ret = g_cur_engine.pefuncs->set_pitch(pitch);
1231         if (0 != ret) {
1232                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to set pitch : pitch(%d), result(%s)",
1233                          pitch, __ttsd_get_engine_error_code(ret));
1234                 return TTSD_ERROR_OPERATION_FAILED;
1235         }
1236
1237         g_cur_engine.default_pitch = pitch;
1238
1239         return 0;
1240 }
1241
1242 /******************************************************************************************
1243 * TTS Engine Interfaces for client
1244 *******************************************************************************************/
1245
1246 int ttsd_engine_load_voice(const char* lang, const int vctype)
1247 {
1248         /* 1. Find voice info */
1249         int ret = -1;
1250         GSList *iter = NULL;
1251         ttsvoice_s* data = NULL;
1252
1253         iter = g_slist_nth(g_cur_voices, 0);
1254         while (NULL != iter) {
1255                 /*Get handle data from list*/
1256                 data = iter->data;
1257
1258                 if (NULL != data) {
1259                         if (0 == strcmp(data->lang, lang) && data->type == vctype) {
1260                                 SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Find voice : default(%d) loaded(%d) ref(%d) lang(%s) type(%d)",
1261                                          data->is_default, data->is_loaded,  data->client_ref_count, data->lang, data->type);
1262                                 break;
1263                         }
1264                 }
1265
1266                 /*Get next item*/
1267                 iter = g_slist_next(iter);
1268                 data = NULL;
1269         }
1270
1271         if (NULL == data) {
1272                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] This voice is not supported voice : lang(%s) type(%d)", lang, vctype);
1273                 return TTSD_ERROR_OPERATION_FAILED;
1274         }
1275
1276         /* 2. increse ref count */
1277         data->client_ref_count++;
1278
1279         /* 3. if ref count change 0 to 1 and not default, load voice */
1280         if (1 == data->client_ref_count && false == data->is_default) {
1281                 /* load voice */
1282                 if (NULL != g_cur_engine.pefuncs->load_voice) {
1283                         ret = g_cur_engine.pefuncs->load_voice(data->lang, data->type);
1284                         if (0 == ret) {
1285                                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Load voice : lang(%s), type(%d)", 
1286                                         data->lang, data->type);
1287                                 data->is_loaded = true;
1288                         } else {
1289                                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to load voice : lang(%s), type(%d), result(%s)",
1290                                         data->lang, data->type, __ttsd_get_engine_error_code(ret));
1291
1292                                 return TTSD_ERROR_OPERATION_FAILED;
1293                         }
1294                 } else {
1295                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent ERROR] Load voice of engine function is NULL");
1296                 }
1297         } else {
1298                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Not load voice : default voice(%d) or ref count(%d)",
1299                         data->is_default, data->client_ref_count);
1300         }
1301
1302 #ifdef ENGINE_AGENT_DEBUG
1303         ttsd_print_voicelist();
1304 #endif
1305
1306         return 0;
1307 }
1308
1309 int ttsd_engine_unload_voice(const char* lang, const int vctype)
1310 {
1311         /* 1. Find voice info */
1312         int ret = -1;
1313         GSList *iter = NULL;
1314         ttsvoice_s* data = NULL;
1315
1316         iter = g_slist_nth(g_cur_voices, 0);
1317         while (NULL != iter) {
1318                 /*Get handle data from list*/
1319                 data = iter->data;
1320
1321                 if (NULL != data) {
1322                         if (0 == strcmp(data->lang, lang) && data->type == vctype) {
1323                                 SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Find voice : default(%d) loaded(%d) ref(%d) lang(%s) type(%d)",
1324                                          data->is_default, data->is_loaded,  data->client_ref_count, data->lang, data->type);
1325                                 break;
1326                         }
1327                 }
1328
1329                 /*Get next item*/
1330                 iter = g_slist_next(iter);
1331                 data = NULL;
1332         }
1333
1334         if (NULL == data) {
1335                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] This voice is not supported voice : lang(%s) type(%d)", lang, vctype);
1336                 return TTSD_ERROR_OPERATION_FAILED;
1337         }
1338
1339         /* 2. Decrese ref count */
1340         data->client_ref_count--;
1341
1342         /* 3. if ref count change 0 and not default, load voice */
1343         if (0 == data->client_ref_count && false == data->is_default) {
1344                 /* load voice */
1345                 if (NULL != g_cur_engine.pefuncs->unload_voice) {
1346                         ret = g_cur_engine.pefuncs->unload_voice(data->lang, data->type);
1347                         if (0 == ret) {
1348                                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Unload voice : lang(%s), type(%d)", 
1349                                         data->lang, data->type);
1350                                 data->is_loaded = false;
1351                         } else {
1352                                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to unload voice : lang(%s), type(%d), result(%s)",
1353                                         data->lang, data->type, __ttsd_get_engine_error_code(ret));
1354
1355                                 return TTSD_ERROR_OPERATION_FAILED;
1356                         }
1357                 } else {
1358                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent ERROR] Unload voice of engine function is NULL");
1359                 }
1360         } else {
1361                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Not unload voice : default voice(%d) or ref count(%d)",
1362                         data->is_default, data->client_ref_count);
1363         }
1364
1365 #ifdef ENGINE_AGENT_DEBUG
1366         ttsd_print_voicelist();
1367 #endif
1368         return 0;
1369 }
1370
1371 int ttsd_engine_start_synthesis(const char* lang, int vctype, const char* text, int speed, void* user_param)
1372 {
1373         if (false == g_agent_init) {
1374                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
1375                 return TTSD_ERROR_OPERATION_FAILED;
1376         }
1377
1378         if (false == g_cur_engine.is_loaded) {
1379                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1380                 return TTSD_ERROR_OPERATION_FAILED;
1381         }
1382
1383         /* select voice for default */
1384         char* temp_lang = NULL;
1385         int temp_type;
1386         if (true != ttsd_engine_select_valid_voice(lang, vctype, &temp_lang, &temp_type)) {
1387                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to select default voice");
1388                 if (NULL != temp_lang)  free(temp_lang);
1389                 return TTSD_ERROR_INVALID_VOICE;
1390         } else {
1391                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Start synthesis : language(%s), type(%d), speed(%d), text(%s)", 
1392                         temp_lang, temp_type, speed, text);
1393         }
1394
1395         if (NULL == g_cur_engine.pefuncs->start_synth) {
1396                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] start_synth() of engine is NULL!!");
1397                 if (NULL != temp_lang)  free(temp_lang);
1398                 return TTSD_ERROR_OPERATION_FAILED;
1399         }
1400
1401         int temp_speed;
1402
1403         if (0 == speed) {
1404                 temp_speed = g_cur_engine.default_speed;
1405         } else {
1406                 temp_speed = speed;
1407         }
1408
1409         /* synthesize text */
1410         int ret = 0;
1411         ret = g_cur_engine.pefuncs->start_synth(temp_lang, temp_type, text, temp_speed, user_param);
1412         if (0 != ret) {
1413                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] ***************************************");
1414                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] * synthesize error : %s *", __ttsd_get_engine_error_code(ret));
1415                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] ***************************************");
1416                 if (NULL != temp_lang)  free(temp_lang);
1417                 return TTSD_ERROR_OPERATION_FAILED;
1418         }
1419
1420         if (NULL != temp_lang)  free(temp_lang);
1421         return 0;
1422 }
1423
1424 int ttsd_engine_cancel_synthesis()
1425 {
1426         if (false == g_agent_init) {
1427                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
1428                 return TTSD_ERROR_OPERATION_FAILED;
1429         }
1430
1431         if (false == g_cur_engine.is_loaded) {
1432                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1433                 return TTSD_ERROR_OPERATION_FAILED;
1434         }
1435
1436         if (NULL == g_cur_engine.pefuncs->cancel_synth) {
1437                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] cancel_synth() of engine is NULL!!");
1438                 return TTSD_ERROR_OPERATION_FAILED;
1439         }
1440
1441         /* stop synthesis */
1442         int ret = 0;
1443         ret = g_cur_engine.pefuncs->cancel_synth();
1444         if (0 != ret) {
1445                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail cancel synthesis : %s", __ttsd_get_engine_error_code(ret));
1446                 return TTSD_ERROR_OPERATION_FAILED;
1447         }
1448
1449         return 0;
1450 }
1451
1452 bool __supported_voice_cb(const char* language, int type, void* user_data)
1453 {
1454         GList** voice_list = (GList**)user_data;
1455
1456         if (NULL == language || NULL == voice_list) {
1457                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!");
1458                 return false;
1459         }
1460
1461         voice_s* voice = calloc(1, sizeof(voice_s));
1462         voice->language = strdup(language);
1463         voice->type = type;
1464
1465         *voice_list = g_list_append(*voice_list, voice);
1466
1467         return true;
1468 }
1469
1470 int ttsd_engine_get_voice_list(GList** voice_list)
1471 {
1472         if (false == g_agent_init) {
1473                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
1474                 return TTSD_ERROR_OPERATION_FAILED;
1475         }
1476
1477         if (false == g_cur_engine.is_loaded) {
1478                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1479                 return TTSD_ERROR_OPERATION_FAILED;
1480         }
1481
1482         int ret = 0;
1483         ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, (void*)voice_list);
1484         if (0 != ret) {
1485                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to get voice list : %s", __ttsd_get_engine_error_code(ret));
1486                 return TTSD_ERROR_OPERATION_FAILED;
1487         }
1488
1489         return 0;
1490 }
1491
1492 int ttsd_engine_get_default_voice(char** lang, int* vctype)
1493 {
1494         if (false == g_agent_init) {
1495                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
1496                 return TTSD_ERROR_OPERATION_FAILED;
1497         }
1498
1499         if (false == g_cur_engine.is_loaded) {
1500                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1501                 return TTSD_ERROR_OPERATION_FAILED;
1502         }
1503
1504         if (NULL == lang || NULL == vctype) {
1505                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] BAD Parameter");
1506                 return TTSD_ERROR_INVALID_PARAMETER;
1507         }
1508
1509         if (NULL != g_cur_engine.default_lang) {
1510                 *lang = strdup(g_cur_engine.default_lang);
1511                 *vctype = g_cur_engine.default_vctype;
1512
1513                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine] Get default voice : language(%s), type(%d)", *lang, *vctype);
1514         } else {
1515                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Default voice is NULL");
1516                 return TTSD_ERROR_OPERATION_FAILED;
1517         }
1518
1519         return 0;
1520 }
1521
1522 void __free_voice_list(GList* voice_list)
1523 {
1524         GList *iter = NULL;
1525         voice_s* data = NULL;
1526
1527         /* if list have item */
1528         if (g_list_length(voice_list) > 0) {
1529                 /* Get a first item */
1530                 iter = g_list_first(voice_list);
1531
1532                 while (NULL != iter) {
1533                         data = iter->data;
1534
1535                         if (NULL != data) {
1536                                 if (NULL != data->language)     free(data->language);
1537                                 free(data);
1538                         }
1539
1540                         voice_list = g_list_remove_link(voice_list, iter);
1541
1542                         iter = g_list_first(voice_list);
1543                 }
1544         }
1545 }
1546
1547 /*
1548 * TTS Engine Callback Functions                                                                                 `                                 *
1549 */
1550 bool __result_cb(ttsp_result_event_e event, const void* data, unsigned int data_size, ttsp_audio_type_e audio_type, int rate, void *user_data)
1551 {
1552         g_result_cb(event, data, data_size, audio_type, rate, user_data);
1553         return true;
1554 }
1555
1556 /* function for debugging */
1557 int ttsd_print_enginelist()
1558 {
1559         GList *iter = NULL;
1560         ttsengine_info_s *data = NULL;
1561
1562         if (g_list_length(g_engine_list) > 0) {
1563                 iter = g_list_first(g_engine_list);
1564
1565                 SLOG(LOG_DEBUG, get_tag(), "----- engine list -----");
1566
1567                 int i = 1;
1568                 while (NULL != iter) {
1569                         data = iter->data;
1570
1571                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[%dth]", i);
1572                         SECURE_SLOG(LOG_DEBUG, get_tag(), "engine uuid : %s", data->engine_uuid);
1573                         SECURE_SLOG(LOG_DEBUG, get_tag(), "engine name : %s", data->engine_name);
1574                         SECURE_SLOG(LOG_DEBUG, get_tag(), "engine path : %s", data->engine_path);
1575                         SECURE_SLOG(LOG_DEBUG, get_tag(), "setting ug path : %s", data->setting_ug_path);
1576
1577                         iter = g_list_next(iter);
1578                         i++;
1579                 }
1580                 SLOG(LOG_DEBUG, get_tag(), "-----------------------");
1581                 SLOG(LOG_DEBUG, get_tag(), "  ");
1582         } else {
1583                 SLOG(LOG_DEBUG, get_tag(), "----- engine list -----");
1584                 SLOG(LOG_DEBUG, get_tag(), "No Engine in directory");
1585                 SLOG(LOG_DEBUG, get_tag(), "-----------------------");
1586         }
1587
1588         return 0;
1589 }
1590
1591 int ttsd_print_voicelist()
1592 {
1593         /* Test log */
1594         GSList *iter = NULL;
1595         ttsvoice_s* data = NULL;
1596
1597         SLOG(LOG_DEBUG, get_tag(), "=== Voice list ===");
1598
1599         if (g_slist_length(g_cur_voices) > 0) {
1600                 /* Get a first item */
1601                 iter = g_slist_nth(g_cur_voices, 0);
1602
1603                 int i = 1;
1604                 while (NULL != iter) {
1605                         /*Get handle data from list*/
1606                         data = iter->data;
1607
1608                         if (NULL == data || NULL == data->lang) {
1609                                 SLOG(LOG_ERROR, get_tag(), "[ERROR] Data is invalid");
1610                                 return 0;
1611                         }
1612
1613                         SLOG(LOG_DEBUG, get_tag(), "[%dth] default(%d) loaded(%d) ref(%d) lang(%s) type(%d)",
1614                                  i, data->is_default, data->is_loaded,  data->client_ref_count, data->lang, data->type);
1615
1616                         /*Get next item*/
1617                         iter = g_slist_next(iter);
1618                         i++;
1619                 }
1620         }
1621
1622         SLOG(LOG_DEBUG, get_tag(), "==================");
1623
1624         return 0;
1625 }