Change to TTS engine process
[platform/core/uifw/tts.git] / common / tts_config_mgr.c
1 /*
2 *  Copyright (c) 2011-2016 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 #include <dirent.h>
15 #include <dlfcn.h>
16 #include <dlog.h>
17 #include <Ecore.h>
18 #include <fcntl.h>
19 #include <glib.h>
20 #include <unistd.h>
21 #include <sys/inotify.h>
22 #include <vconf.h>
23
24 #include "tts_config_mgr.h"
25 #include "tts_config_parser.h"
26 #include "tts_defs.h"
27
28 typedef struct {
29         int     uid;
30         tts_config_engine_changed_cb            engine_cb;
31         tts_config_voice_changed_cb             voice_cb;
32         tts_config_speech_rate_changed_cb       speech_cb;
33         tts_config_screen_reader_changed_cb     screen_cb;
34         tts_config_pitch_changed_cb             pitch_cb;
35         void*   user_data;
36 } tts_config_client_s;
37
38 extern char* tts_tag();
39
40 static GSList* g_engine_list = NULL;
41
42 static GSList* g_config_client_list = NULL;
43
44 static tts_config_s* g_config_info = NULL;
45
46 static Ecore_Fd_Handler* g_config_fd_handler_noti = NULL;
47 static int g_config_fd_noti;
48 static int g_config_wd_noti;
49
50 /* For engine directory monitoring */
51 typedef struct {
52         Ecore_Fd_Handler* dir_fd_handler;
53         int dir_fd;
54         int dir_wd;
55 } tts_engine_inotify_s;
56
57 static GList* g_ino_list = NULL;
58
59 int __tts_config_mgr_print_engine_info();
60 static int __tts_config_mgr_register_engine_config_updated_event(const char* path);
61 static int __tts_config_mgr_unregister_engine_config_updated_event();
62
63 int __tts_config_mgr_check_engine_is_valid(const char* engine_id)
64 {
65         if (NULL == engine_id) {
66                 SLOG(LOG_ERROR, tts_tag(), "Input parameter is NULL");
67                 return -1;
68         }
69
70         GSList *iter = NULL;
71         tts_engine_info_s *engine_info = NULL;
72
73         if (0 >= g_slist_length(g_engine_list)) {
74                 SLOG(LOG_ERROR, tts_tag(), "There is no engine!!");
75                 return -1;
76         }
77
78         /* Get a first item */
79         iter = g_slist_nth(g_engine_list, 0);
80
81         while (NULL != iter) {
82                 engine_info = iter->data;
83
84                 if (NULL == engine_info) {
85                         SLOG(LOG_ERROR, tts_tag(), "engine info is NULL");
86                         return -1;
87                 }
88
89                 if (0 == strcmp(engine_id, engine_info->uuid)) {
90                         SLOG(LOG_DEBUG, tts_tag(), "Default engine is valid : %s", engine_id);
91                         return 0;
92                 }
93
94                 iter = g_slist_next(iter);
95         }
96
97         /* Change default engine */
98         iter = g_slist_nth(g_engine_list, 0);
99         if (NULL == iter) {
100                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] No engine in list");
101                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
102         }
103
104         engine_info = iter->data;
105         if (NULL == g_config_info) {
106                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Invalid engine info in list");
107                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
108         }
109
110         if (NULL != g_config_info->engine_id)   free(g_config_info->engine_id);
111         if (NULL != g_config_info->setting)     free(g_config_info->setting);
112
113         g_config_info->engine_id = strdup(engine_info->uuid);
114         g_config_info->setting = strdup(engine_info->setting);
115
116         SLOG(LOG_DEBUG, tts_tag(), "Default engine is changed : %s", g_config_info->engine_id);
117
118         /* Change is default voice */
119         GSList *iter_voice = NULL;
120         tts_config_voice_s* voice = NULL;
121         bool is_valid_voice = false;
122
123         /* Get a first item */
124         iter_voice = g_slist_nth(engine_info->voices, 0);
125
126         while (NULL != iter_voice) {
127                 /*Get handle data from list*/
128                 voice = iter_voice->data;
129
130                 if (NULL != voice) {
131                         if (NULL != voice->language && NULL != g_config_info->language) {
132                                 if (0 == strcmp(voice->language, g_config_info->language)) {
133                                         if (voice->type == g_config_info->type) {
134                                                 /* language is valid */
135                                                 is_valid_voice = true;
136
137                                                 free(g_config_info->language);
138                                                 g_config_info->language = strdup(voice->language);
139                                                 g_config_info->type = voice->type;
140
141                                                 SLOG(LOG_DEBUG, tts_tag(), "Default voice is changed : lang(%s) type(%d)", voice->language, voice->type);
142                                                 break;
143                                         }
144                                 }
145                         }
146                 }
147
148                 iter_voice = g_slist_next(iter_voice);
149         }
150
151         if (false == is_valid_voice) {
152                 /* Select first voice as default */
153                 if (NULL != g_config_info->language) {
154                         free(g_config_info->language);
155
156                         iter_voice = g_slist_nth(engine_info->voices, 0);
157                         if (NULL == iter_voice) {
158                                 SLOG(LOG_ERROR, tts_tag(), "Fail to get voice list");
159                                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
160                         }
161                         voice = iter_voice->data;
162
163                         if (NULL == voice || NULL == voice->language) {
164                                 SLOG(LOG_ERROR, tts_tag(), "Fail to get voice info from list");
165                                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
166                         }
167
168                         g_config_info->language = strdup(voice->language);
169                         g_config_info->type = voice->type;
170                         SLOG(LOG_DEBUG, tts_tag(), "Default voice is changed : lang(%s) type(%d)", voice->language, voice->type);
171                 }
172         }
173
174         if (0 != tts_parser_set_engine(g_config_info->engine_id, g_config_info->setting, 
175                 g_config_info->language, g_config_info->type)) {
176                 SLOG(LOG_ERROR, tts_tag(), " Fail to save config");
177                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
178         }
179
180         return 0;
181 }
182
183 bool __tts_config_mgr_check_lang_is_valid(const char* engine_id, const char* language, int type)
184 {
185         if (NULL == engine_id || NULL == language) {
186                 SLOG(LOG_ERROR, tts_tag(), "Input parameter is NULL");
187                 return false;
188         }
189
190         GSList *iter = NULL;
191         tts_engine_info_s *engine_info = NULL;
192
193         if (0 >= g_slist_length(g_engine_list)) {
194                 SLOG(LOG_ERROR, tts_tag(), "There is no engine!!");
195                 return false;
196         }
197
198         /* Get a first item */
199         iter = g_slist_nth(g_engine_list, 0);
200
201         while (NULL != iter) {
202                 engine_info = iter->data;
203
204                 if (NULL == engine_info) {
205                         SLOG(LOG_ERROR, tts_tag(), "engine info is NULL");
206                         return false;
207                 }
208
209                 if (0 != strcmp(engine_id, engine_info->uuid)) {
210                         iter = g_slist_next(iter);
211                         continue;
212                 }
213
214                 GSList *iter_voice = NULL;
215                 tts_config_voice_s* voice = NULL;
216
217                 if (g_slist_length(engine_info->voices) <= 0) {
218                         SLOG(LOG_ERROR, tts_tag(), "There is no voice : %s", engine_info->uuid);
219                         iter = g_slist_next(iter);
220                         return false;
221                 }
222
223                 /* Get a first item */
224                 iter_voice = g_slist_nth(engine_info->voices, 0);
225
226                 int i = 1;
227                 while (NULL != iter_voice) {
228                         /*Get handle data from list*/
229                         voice = iter_voice->data;
230
231                         if (NULL != voice) {
232                                 if (0 == strcmp(language, voice->language)) {
233                                         if (type == voice->type) {
234                                                 return true;
235                                         }
236                                 }
237                         }
238
239                         /*Get next item*/
240                         iter_voice = g_slist_next(iter_voice);
241                         i++;
242                 }
243
244                 return false;
245         }
246
247         return false;
248 }
249
250 int __tts_config_mgr_select_lang(const char* engine_id, char** language, int* type)
251 {
252         if (NULL == engine_id || NULL == language) {
253                 SLOG(LOG_ERROR, tts_tag(), "Input parameter is NULL");
254                 return false;
255         }
256
257         GSList *iter = NULL;
258         tts_engine_info_s *engine_info = NULL;
259
260         if (0 >= g_slist_length(g_engine_list)) {
261                 SLOG(LOG_ERROR, tts_tag(), "There is no engine!!");
262                 return false;
263         }
264
265         /* Get a first item */
266         iter = g_slist_nth(g_engine_list, 0);
267
268         while (NULL != iter) {
269                 engine_info = iter->data;
270
271                 if (NULL == engine_info) {
272                         SLOG(LOG_ERROR, tts_tag(), "engine info is NULL");
273                         return false;
274                 }
275
276                 if (0 != strcmp(engine_id, engine_info->uuid)) {
277                         iter = g_slist_next(iter);
278                         continue;
279                 }
280
281                 GSList *iter_voice = NULL;
282                 tts_config_voice_s* voice = NULL;
283
284                 if (g_slist_length(engine_info->voices) <= 0) {
285                         SLOG(LOG_ERROR, tts_tag(), "There is no voice : %s", engine_info->uuid);
286                         return -1;
287                 }
288
289                 /* Get a first item */
290                 iter_voice = g_slist_nth(engine_info->voices, 0);
291
292                 while (NULL != iter_voice) {
293                         voice = iter_voice->data;
294                         if (NULL != voice) {
295                                 /* Default language */
296                                 if (0 == strcmp(TTS_BASE_LANGUAGE, voice->language)) {
297                                         *language = strdup(voice->language);
298                                         *type = voice->type;
299
300                                         SECURE_SLOG(LOG_DEBUG, tts_tag(), "Selected language(%s) type(%d)", *language, *type);
301                                         return 0;
302                                 }
303                         }
304                         iter_voice = g_slist_next(iter_voice);
305                 }
306
307                 /* Not support base language */
308                 if (NULL != voice) {
309                         *language = strdup(voice->language);
310                         *type = voice->type;
311
312                         SECURE_SLOG(LOG_DEBUG, tts_tag(), "Selected language(%s) type(%d)", *language, *type);
313                         return 0;
314                 }
315                 break;
316         }
317
318         return -1;
319 }
320
321 Eina_Bool tts_config_mgr_inotify_event_cb(void* data, Ecore_Fd_Handler *fd_handler)
322 {
323         SLOG(LOG_DEBUG, tts_tag(), "===== Config changed callback event");
324
325         int length;
326         struct inotify_event event;
327         memset(&event, '\0', sizeof(struct inotify_event));
328
329         length = read(g_config_fd_noti, &event, sizeof(struct inotify_event));
330         if (0 > length) {
331                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty Inotify event");
332                 SLOG(LOG_DEBUG, tts_tag(), "=====");
333                 SLOG(LOG_DEBUG, tts_tag(), " ");
334                 return ECORE_CALLBACK_DONE;
335         }
336
337         if (IN_CLOSE_WRITE == event.mask) {
338                 /* check config changed state */
339                 char* engine = NULL;
340                 char* setting = NULL;
341                 char* lang = NULL;
342                 bool auto_voice = g_config_info->auto_voice;
343                 int voice_type = -1;
344                 int speech_rate = -1;
345                 int pitch = -1;
346
347                 GSList *iter = NULL;
348                 tts_config_client_s* temp_client = NULL;
349
350                 if (0 != tts_parser_find_config_changed(&engine, &setting, &auto_voice, &lang, &voice_type, &speech_rate, &pitch))
351                         return ECORE_CALLBACK_PASS_ON;
352
353                 /* engine changed */
354                 if (NULL != engine || NULL != setting) {
355                         if (NULL != engine) {
356                                 if (NULL != g_config_info->engine_id)
357                                         free(g_config_info->engine_id);
358
359                                 g_config_info->engine_id = strdup(engine);
360                         }
361                         if (NULL != setting) {
362                                 if (NULL != g_config_info->setting)
363                                         free(g_config_info->setting);
364
365                                 g_config_info->setting = strdup(setting);
366                         }
367
368                         SECURE_SLOG(LOG_DEBUG, tts_tag(), "Engine change(%s)", g_config_info->engine_id);
369
370                         /* Call all callbacks of client*/
371                         iter = g_slist_nth(g_config_client_list, 0);
372
373                         while (NULL != iter) {
374                                 temp_client = iter->data;
375
376                                 if (NULL != temp_client) {
377                                         if (NULL != temp_client->engine_cb) {
378                                                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "Engine changed callback : uid(%d)", temp_client->uid);
379                                                 temp_client->engine_cb(g_config_info->engine_id, g_config_info->setting, 
380                                                         g_config_info->language, g_config_info->type, 
381                                                         g_config_info->auto_voice, g_config_info->credential, temp_client->user_data);
382                                         }
383                                 }
384
385                                 iter = g_slist_next(iter);
386                         }
387                 }
388
389                 if (auto_voice != g_config_info->auto_voice) {
390                         g_config_info->auto_voice = auto_voice;
391                 }
392
393                 if (NULL != lang || -1 != voice_type) {
394                         char* before_lang = NULL;
395                         int before_type;
396
397                         before_lang = strdup(g_config_info->language);
398                         before_type = g_config_info->type;
399
400                         if (NULL != lang) {
401                                 if (NULL != g_config_info->language)
402                                         free(g_config_info->language);
403
404                                 g_config_info->language = strdup(lang);
405                         }
406                         if (-1 != voice_type) {
407                                 g_config_info->type = voice_type;
408                         }
409
410                         SECURE_SLOG(LOG_DEBUG, tts_tag(), "Voice change(%s, %d)", g_config_info->language, g_config_info->type);
411
412                         /* Call all callbacks of client*/
413                         iter = g_slist_nth(g_config_client_list, 0);
414
415                         while (NULL != iter) {
416                                 temp_client = iter->data;
417
418                                 if (NULL != temp_client) {
419                                         if (NULL != temp_client->voice_cb) {
420                                                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "Voice changed callback : uid(%d)", temp_client->uid);
421                                                 temp_client->voice_cb(before_lang, before_type, 
422                                                         g_config_info->language, g_config_info->type, 
423                                                         g_config_info->auto_voice, temp_client->user_data);
424                                         }
425                                 }
426
427                                 iter = g_slist_next(iter);
428                         }
429
430                         if (NULL != before_lang) {
431                                 free(before_lang);
432                         }
433                 }
434
435                 if (-1 != speech_rate) {
436                         g_config_info->speech_rate = speech_rate;
437
438                         SECURE_SLOG(LOG_DEBUG, tts_tag(), "Speech rate change(%d)", g_config_info->speech_rate);
439
440                         /* Call all callbacks of client*/
441                         iter = g_slist_nth(g_config_client_list, 0);
442
443                         while (NULL != iter) {
444                                 temp_client = iter->data;
445
446                                 if (NULL != temp_client) {
447                                         if (NULL != temp_client->speech_cb) {
448                                                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "Speech rate changed callback : uid(%d)", temp_client->uid);
449                                                 temp_client->speech_cb(g_config_info->speech_rate, temp_client->user_data);
450                                         }
451                                 }
452
453                                 iter = g_slist_next(iter);
454                         }
455                 }
456
457                 if (-1 != pitch) {
458                         g_config_info->pitch = pitch;
459
460                         SECURE_SLOG(LOG_DEBUG, tts_tag(), "pitch change(%d)", g_config_info->pitch);
461
462                         /* Call all callbacks of client*/
463                         iter = g_slist_nth(g_config_client_list, 0);
464
465                         while (NULL != iter) {
466                                 temp_client = iter->data;
467
468                                 if (NULL != temp_client) {
469                                         if (NULL != temp_client->pitch_cb) {
470                                                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "Pitch changed callback : uid(%d)", temp_client->uid);
471                                                 temp_client->pitch_cb(g_config_info->pitch, temp_client->user_data);
472                                         }
473                                 }
474
475                                 iter = g_slist_next(iter);
476                         }
477                 }
478
479                 if (NULL != engine)     free(engine);
480                 if (NULL != setting)    free(setting);
481                 if (NULL != lang)       free(lang);
482         } else {
483                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Undefined event");
484         }
485
486         SLOG(LOG_DEBUG, tts_tag(), "=====");
487         SLOG(LOG_DEBUG, tts_tag(), " ");
488
489         return ECORE_CALLBACK_PASS_ON;
490 }
491
492 int __tts_config_mgr_register_config_event()
493 {
494         /* get file notification handler */
495         int fd;
496         int wd;
497
498         fd = inotify_init();
499         if (fd < 0) {
500                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail get inotify fd");
501                 return -1;
502         }
503         g_config_fd_noti = fd;
504
505         wd = inotify_add_watch(fd, TTS_CONFIG, IN_CLOSE_WRITE);
506         g_config_wd_noti = wd;
507
508         g_config_fd_handler_noti = ecore_main_fd_handler_add(fd, ECORE_FD_READ,
509                 (Ecore_Fd_Cb)tts_config_mgr_inotify_event_cb, NULL, NULL, NULL);
510         if (NULL == g_config_fd_handler_noti) {
511                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get handler_noti");
512                 return -1;
513         }
514
515         /* Set non-blocking mode of file */
516         int value;
517         value = fcntl(fd, F_GETFL, 0);
518         value |= O_NONBLOCK;
519
520         if (0 > fcntl(fd, F_SETFL, value)) {
521                 SLOG(LOG_WARN, tts_tag(), "[WARNING] Fail to set non-block mode");
522         }
523
524         return 0;
525 }
526
527 int __tts_config_mgr_unregister_config_event()
528 {
529         /* delete inotify variable */
530         ecore_main_fd_handler_del(g_config_fd_handler_noti);
531         inotify_rm_watch(g_config_fd_noti, g_config_wd_noti);
532         close(g_config_fd_noti);
533
534         return 0;
535 }
536
537 int __tts_config_set_auto_language()
538 {
539         char* value = NULL;
540         value = vconf_get_str(TTS_LANGSET_KEY);
541         if (NULL == value) {
542                 SLOG(LOG_ERROR, tts_tag(), "[Config ERROR] Fail to get display language");
543                 return -1;
544         }
545
546         char temp_lang[6] = {'\0', };
547         strncpy(temp_lang, value, 5);
548         free(value);
549
550         if (true == __tts_config_mgr_check_lang_is_valid(g_config_info->engine_id, temp_lang, g_config_info->type)) {
551                 /* tts default voice change */
552                 if (NULL == g_config_info->language) {
553                         SLOG(LOG_ERROR, tts_tag(), "Current config language is NULL");
554                         return -1;
555                 }
556
557                 char* before_lang = NULL;
558                 int before_type;
559
560                 if (0 != tts_parser_set_voice(temp_lang, g_config_info->type)) {
561                         SLOG(LOG_ERROR, tts_tag(), "Fail to save default voice");
562                         return -1;
563                 }
564
565                 before_lang = strdup(g_config_info->language);
566                 before_type = g_config_info->type;
567
568                 free(g_config_info->language);
569                 g_config_info->language = strdup(temp_lang);
570
571                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Config] Default voice : lang(%s) type(%d)", 
572                         g_config_info->language, g_config_info->type);
573
574                 GSList *iter = NULL;
575                 tts_config_client_s* temp_client = NULL;
576
577                 /* Call all callbacks of client*/
578                 iter = g_slist_nth(g_config_client_list, 0);
579
580                 while (NULL != iter) {
581                         temp_client = iter->data;
582
583                         if (NULL != temp_client) {
584                                 if (NULL != temp_client->voice_cb) {
585                                         temp_client->voice_cb(before_lang, before_type, 
586                                                 g_config_info->language, g_config_info->type, 
587                                                 g_config_info->auto_voice, temp_client->user_data);
588                                 }
589                         }
590
591                         iter = g_slist_next(iter);
592                 }
593
594                 if (NULL != before_lang) {
595                         free(before_lang);
596                 }
597         } else {
598                 /* Display language is not valid */
599                 char* tmp_language = NULL;
600                 int tmp_type = -1;
601                 if (0 != __tts_config_mgr_select_lang(g_config_info->engine_id, &tmp_language, &tmp_type)) {
602                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to select language");
603                         return -1;
604                 }
605
606                 if (NULL == tmp_language) {
607                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] language is NULL");
608                         return -1;
609                 }
610
611                 if (0 != tts_parser_set_voice(tmp_language, tmp_type)) {
612                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to save config");
613                         return -1;
614                 }
615
616                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Config] Default voice : lang(%s) type(%d)", 
617                         tmp_language, tmp_type);
618
619                 GSList *iter = NULL;
620                 tts_config_client_s* temp_client = NULL;
621
622                 /* Call all callbacks of client*/
623                 iter = g_slist_nth(g_config_client_list, 0);
624
625                 while (NULL != iter) {
626                         temp_client = iter->data;
627
628                         if (NULL != temp_client) {
629                                 if (NULL != temp_client->voice_cb) {
630                                         temp_client->voice_cb(g_config_info->language, g_config_info->type, 
631                                                 tmp_language, tmp_type, g_config_info->auto_voice, temp_client->user_data);
632                                 }
633                         }
634
635                         iter = g_slist_next(iter);
636                 }
637
638                 if (NULL != g_config_info->language) {
639                         free(g_config_info->language);
640                         g_config_info->language = strdup(tmp_language);
641                 }
642
643                 g_config_info->type = tmp_type;
644
645                 free(tmp_language);
646         }
647
648         return 0;
649 }
650
651 void __tts_config_display_language_changed_cb(keynode_t *key, void *data)
652 {
653         if (true == g_config_info->auto_voice) {
654                 __tts_config_set_auto_language();
655         }
656
657         return;
658 }
659
660 void __tts_config_screen_reader_changed_cb(keynode_t *key, void *data)
661 {
662         int ret;
663         int screen_reader;
664         ret = vconf_get_bool(TTS_ACCESSIBILITY_KEY, &screen_reader);
665         if (0 != ret) {
666                 SLOG(LOG_ERROR, tts_tag(), "[Config ERROR] Fail to get screen reader");
667                 return;
668         }
669
670         GSList *iter = NULL;
671         tts_config_client_s* temp_client = NULL;
672
673         /* Call all callbacks of client*/
674         iter = g_slist_nth(g_config_client_list, 0);
675
676         while (NULL != iter) {
677                 temp_client = iter->data;
678
679                 if (NULL != temp_client) {
680                         if (NULL != temp_client->screen_cb) {
681                                 temp_client->screen_cb((bool)screen_reader);
682                         }
683                 }
684
685                 iter = g_slist_next(iter);
686         }
687 }
688
689 int __tts_config_release_client(int uid)
690 {
691         GSList *iter = NULL;
692         tts_config_client_s* temp_client = NULL;
693
694         if (0 < g_slist_length(g_config_client_list)) {
695                 /* Check uid */
696                 iter = g_slist_nth(g_config_client_list, 0);
697
698                 while (NULL != iter) {
699                         temp_client = iter->data;
700
701                         if (NULL != temp_client) {
702                                 if (uid == temp_client->uid) {
703                                         g_config_client_list = g_slist_remove(g_config_client_list, temp_client);
704                                         free(temp_client);
705                                         temp_client = NULL;
706                                         break;
707                                 }
708                         }
709
710                         iter = g_slist_next(iter);
711                 }
712         }
713
714         SLOG(LOG_DEBUG, tts_tag(), "Client count (%d)", g_slist_length(g_config_client_list));
715
716         return g_slist_length(g_config_client_list);
717 }
718
719 void __tts_config_release_engine()
720 {
721         GSList *iter = NULL;
722         tts_engine_info_s *engine_info = NULL;
723
724         if (0 < g_slist_length(g_engine_list)) {
725
726                 /* Get a first item */
727                 iter = g_slist_nth(g_engine_list, 0);
728
729                 while (NULL != iter) {
730                         engine_info = iter->data;
731
732                         if (NULL != engine_info) {
733                                 g_engine_list = g_slist_remove(g_engine_list, engine_info);
734
735                                 tts_parser_free_engine_info(engine_info);
736                         }
737
738                         iter = g_slist_nth(g_engine_list, 0);
739                 }
740         }
741
742         return;
743 }
744
745 int __tts_config_mgr_get_engine_info()
746 {
747         DIR *dp = NULL;
748         int ret = -1;
749         struct dirent entry;
750         struct dirent *dirp = NULL;
751
752         char filepath[512] = {'\0',};
753         int filesize;
754         tts_engine_info_s* info = NULL;
755
756         __tts_config_release_engine();
757         g_engine_list = NULL;
758         __tts_config_mgr_unregister_engine_config_updated_event();
759
760         /* Copy default info directory to download directory */
761         dp  = opendir(TTS_DEFAULT_ENGINE_INFO);
762         if (NULL == dp) {
763                 SLOG(LOG_DEBUG, tts_tag(), "[CONFIG] No default directory : %s", TTS_DEFAULT_ENGINE_INFO);
764         } else {
765                 do {
766                         ret = readdir_r(dp, &entry, &dirp);
767                         if (0 != ret) {
768                                 SLOG(LOG_ERROR, tts_tag(), "[CONFIG] Fail to read directory");
769                                 break;
770                         }
771
772                         if (NULL != dirp) {
773                                 filesize = strlen(TTS_DEFAULT_ENGINE_INFO) + strlen(dirp->d_name) + 2;
774                                 if (filesize >= 512) {
775                                         SECURE_SLOG(LOG_ERROR, tts_tag(), "[CONFIG ERROR] File path is too long : %s", dirp->d_name);
776                                         closedir(dp);
777                                         return -1;
778                                 }
779
780                                 memset(filepath, '\0', 512);
781                                 snprintf(filepath, 512, "%s/%s", TTS_DEFAULT_ENGINE_INFO, dirp->d_name);
782
783                                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[CONFIG] Filepath(%s)", filepath);
784
785                                 char dest[512] = {'\0',};
786                                 snprintf(dest, 512, "%s/%s", TTS_DOWNLOAD_ENGINE_INFO, dirp->d_name);
787
788                                 if (0 != access(dest, F_OK)) {
789                                         if (0 != tts_parser_copy_xml(filepath, dest)) {
790                                                 SLOG(LOG_ERROR, tts_tag(), "[CONFIG ERROR] Fail to copy engine info");
791                                         }
792                                 }
793                         }
794                 } while (NULL != dirp);
795
796                 closedir(dp);
797         }
798
799         /* Get engine info from default engine directory */
800         dp  = opendir(TTS_DOWNLOAD_ENGINE_INFO);
801         if (NULL == dp) {
802                 SLOG(LOG_DEBUG, tts_tag(), "[CONFIG] No downloadable directory : %s", TTS_DOWNLOAD_ENGINE_INFO);
803         } else {
804                 do {
805                         ret = readdir_r(dp, &entry, &dirp);
806                         if (0 != ret) {
807                                 SLOG(LOG_ERROR, tts_tag(), "[CONFIG] Fail to read directory");
808                                 break;
809                         }
810
811                         if (NULL != dirp) {
812                                 filesize = strlen(TTS_DOWNLOAD_ENGINE_INFO) + strlen(dirp->d_name) + 2;
813                                 if (filesize >= 512) {
814                                         SECURE_SLOG(LOG_ERROR, tts_tag(), "[CONFIG ERROR] File path is too long : %s", dirp->d_name);
815                                         closedir(dp);
816                                         return -1;
817                                 }
818
819                                 memset(filepath, '\0', 512);
820                                 snprintf(filepath, 512, "%s/%s", TTS_DOWNLOAD_ENGINE_INFO, dirp->d_name);
821
822                                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[CONFIG] Filepath(%s)", filepath);
823
824                                 if (0 == tts_parser_get_engine_info(filepath, &info)) {
825                                         g_engine_list = g_slist_append(g_engine_list, info);
826                                         if (0 != __tts_config_mgr_register_engine_config_updated_event(filepath)) {
827                                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to register engine config updated event");
828                                         }
829                                 }
830                         }
831                 } while (NULL != dirp);
832
833                 closedir(dp);
834         }
835
836         if (0 >= g_slist_length(g_engine_list)) {
837                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] No engine");
838                 return -1;
839         }
840
841         return 0;
842 }
843
844 static Eina_Bool __tts_config_mgr_engine_config_inotify_event_callback(void* data, Ecore_Fd_Handler *fd_handler)
845 {
846         SLOG(LOG_DEBUG, tts_tag(), "===== Engine config updated callback event");
847
848         tts_engine_inotify_s *ino = (tts_engine_inotify_s *)data;
849         int dir_fd = ino->dir_fd;
850
851         int length;
852         struct inotify_event event;
853         memset(&event, '\0', sizeof(struct inotify_event));
854
855         length = read(dir_fd, &event, sizeof(struct inotify_event));
856         if (0 > length) {
857                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty Inotify event");
858                 SLOG(LOG_DEBUG, tts_tag(), "=====");
859                 SLOG(LOG_DEBUG, tts_tag(), " ");
860                 return ECORE_CALLBACK_DONE;
861         }
862
863         if (IN_CLOSE_WRITE == event.mask) {
864                 int ret = __tts_config_mgr_get_engine_info();
865                 if (0 != ret) {
866                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get engine info when config updated");
867                 }
868                 __tts_config_mgr_print_engine_info();
869                 bool support = tts_config_check_default_voice_is_valid(g_config_info->language, g_config_info->type);
870                 if (false == support) {
871                         SLOG(LOG_DEBUG, tts_tag(), "[ERROR] Default voice is valid");
872                         char* temp_lang = NULL;
873                         int temp_type;
874                         ret = __tts_config_mgr_select_lang(g_config_info->engine_id, &temp_lang, &temp_type);
875                         if (0 != ret) {
876                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get voice");
877                         }
878
879                         ret = tts_config_mgr_set_voice(temp_lang, temp_type);
880                         if (0 != ret) {
881                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to set voice");
882                         } else {
883                                 SLOG(LOG_DEBUG, tts_tag(), "[DEBUG] Saved default voice : lang(%s), type(%d)", g_config_info->language, g_config_info->type);
884                         }
885                         if (NULL != temp_lang)  free(temp_lang);
886                 }
887
888                 GSList *iter = NULL;
889                 tts_config_client_s* temp_client = NULL;
890                 /* Call all callbacks of client*/
891                 iter = g_slist_nth(g_config_client_list, 0);
892
893                 while (NULL != iter) {
894                         temp_client = iter->data;
895
896                         if (NULL != temp_client) {
897                                 if (NULL != temp_client->engine_cb) {
898                                         SECURE_SLOG(LOG_DEBUG, tts_tag(), "Engine changed callback : uid(%d)", temp_client->uid);
899                                         temp_client->engine_cb(g_config_info->engine_id, g_config_info->setting,
900                                                 g_config_info->language, g_config_info->type, 
901                                                 g_config_info->auto_voice, g_config_info->credential, temp_client->user_data);
902                                 }
903                         }
904
905                         iter = g_slist_next(iter);
906                 }
907         } else {
908                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Undefined event");
909         }
910
911         SLOG(LOG_DEBUG, tts_tag(), "=====");
912         SLOG(LOG_DEBUG, tts_tag(), " ");
913
914         return ECORE_CALLBACK_PASS_ON;
915 }
916
917 static int __tts_config_mgr_register_engine_config_updated_event(const char* path)
918 {
919         if (NULL == path) {
920                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Path is NULL");
921                 return -1;
922         }
923
924         /* For engine directory monitoring */
925         tts_engine_inotify_s *ino = (tts_engine_inotify_s *)calloc(1, sizeof(tts_engine_inotify_s));
926         if (NULL == ino) {
927                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to allocate memory");
928                 return -1;
929         }
930
931         ino->dir_fd = inotify_init();
932         if (ino->dir_fd < 0) {
933                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to init inotify");
934                 free(ino);
935                 ino = NULL;
936
937                 return -1;
938         }
939
940         ino->dir_wd = inotify_add_watch(ino->dir_fd, path, IN_CLOSE_WRITE);
941         SLOG(LOG_DEBUG, tts_tag(), "Add inotify watch(%s)", path);
942         if (ino->dir_wd < 0) {
943                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to add watch");
944                 return -1;
945         }
946
947         ino->dir_fd_handler = ecore_main_fd_handler_add(ino->dir_fd, ECORE_FD_READ, (Ecore_Fd_Cb)__tts_config_mgr_engine_config_inotify_event_callback, (void *)ino, NULL, NULL);
948         if (NULL == ino->dir_fd_handler) {
949                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to add fd handler");
950                 return -1;
951         }
952
953         /* Set non-blocking mode of file */
954         int value;
955         value = fcntl(ino->dir_fd, F_GETFL, 0);
956         value |= O_NONBLOCK;
957
958         if (0 > fcntl(ino->dir_fd, F_SETFL, value)) {
959                 SLOG(LOG_WARN, tts_tag(), "[WARNING] Fail to set non-block mode");
960         }
961
962         g_ino_list = g_list_append(g_ino_list, ino);
963
964         return 0;
965 }
966
967 static int __tts_config_mgr_unregister_engine_config_updated_event()
968 {
969         /* delete all inotify variable */
970         if (0 < g_list_length(g_ino_list)) {
971                 GList *iter = NULL;
972                 iter = g_list_first(g_ino_list);
973
974                 while (NULL != iter) {
975                         tts_engine_inotify_s *tmp = iter->data;
976
977                         if (NULL != tmp) {
978                                 ecore_main_fd_handler_del(tmp->dir_fd_handler);
979                                 inotify_rm_watch(tmp->dir_fd, tmp->dir_wd);
980                                 close(tmp->dir_fd);
981
982                                 free(tmp);
983                         }
984
985                         g_ino_list = g_list_remove_link(g_ino_list, iter);
986
987                         iter = g_list_first(g_ino_list);
988                 }
989         }
990
991         return 0;
992 }
993
994 int tts_config_mgr_initialize(int uid)
995 {
996         GSList *iter = NULL;
997         int* get_uid;
998         tts_config_client_s* temp_client = NULL;
999
1000         /* Register uid */
1001         if (0 < g_slist_length(g_config_client_list)) {
1002                 /* Check uid */
1003                 iter = g_slist_nth(g_config_client_list, 0);
1004
1005                 while (NULL != iter) {
1006                         get_uid = iter->data;
1007
1008                         if (uid == *get_uid) {
1009                                 SECURE_SLOG(LOG_WARN, tts_tag(), "[CONFIG] uid(%d) has already registered", uid);
1010                                 return 0;
1011                         }
1012
1013                         iter = g_slist_next(iter);
1014                 }
1015
1016                 temp_client = (tts_config_client_s*)calloc(1, sizeof(tts_config_client_s));
1017                 if (NULL == temp_client) {
1018                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to allocate memory");
1019                         return TTS_CONFIG_ERROR_OUT_OF_MEMORY;
1020                 }
1021                 temp_client->uid = uid;
1022
1023                 g_config_client_list = g_slist_append(g_config_client_list, temp_client);
1024
1025                 SECURE_SLOG(LOG_WARN, tts_tag(), "[CONFIG] Add uid(%d) but config has already initialized", uid);
1026                 return 0;
1027         } else {
1028                 temp_client = (tts_config_client_s*)calloc(1, sizeof(tts_config_client_s));
1029                 if (NULL == temp_client) {
1030                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to allocate memory");
1031                         return TTS_CONFIG_ERROR_OUT_OF_MEMORY;
1032                 }
1033                 temp_client->uid = uid;
1034
1035                 g_config_client_list = g_slist_append(g_config_client_list, temp_client);
1036         }
1037
1038         if (0 != access(TTS_HOME, F_OK)) {
1039                 if (0 != mkdir(TTS_HOME, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1040                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to make directory : %s", TTS_HOME);
1041                         __tts_config_release_client(uid);
1042                         __tts_config_release_engine();
1043                         return TTS_CONFIG_ERROR_OPERATION_FAILED;
1044                 } else {
1045                         SLOG(LOG_DEBUG, tts_tag(), "Success to make directory : %s", TTS_HOME);
1046                 }
1047         }
1048
1049         if (0 != access(TTS_CONFIG_BASE, F_OK)) {
1050                 if (0 != mkdir(TTS_CONFIG_BASE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1051                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to make directory : %s", TTS_CONFIG_BASE);
1052                         __tts_config_release_client(uid);
1053                         __tts_config_release_engine();
1054                         return TTS_CONFIG_ERROR_OPERATION_FAILED;
1055                 } else {
1056                         SLOG(LOG_DEBUG, tts_tag(), "Success to make directory : %s", TTS_CONFIG_BASE);
1057                 }
1058         }
1059
1060         if (0 != access(TTS_DOWNLOAD_BASE, F_OK)) {
1061                 if (0 != mkdir(TTS_DOWNLOAD_BASE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1062                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to make directory : %s", TTS_DOWNLOAD_BASE);
1063                         __tts_config_release_client(uid);
1064                         __tts_config_release_engine();
1065                         return TTS_CONFIG_ERROR_OPERATION_FAILED;
1066                 } else {
1067                         SLOG(LOG_DEBUG, tts_tag(), "Success to make directory : %s", TTS_DOWNLOAD_BASE);
1068                 }
1069         }
1070
1071         if (0 != access(TTS_DOWNLOAD_ENGINE_INFO, F_OK)) {
1072                 if (0 != mkdir(TTS_DOWNLOAD_ENGINE_INFO, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1073                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to make directory : %s", TTS_DOWNLOAD_ENGINE_INFO);
1074                         __tts_config_release_client(uid);
1075                         __tts_config_release_engine();
1076                         return TTS_CONFIG_ERROR_OPERATION_FAILED;
1077                 } else {
1078                         SLOG(LOG_DEBUG, tts_tag(), "Success to make directory : %s", TTS_DOWNLOAD_ENGINE_INFO);
1079                 }
1080         }
1081
1082         if (0 != __tts_config_mgr_get_engine_info()) {
1083                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get engine info");
1084                 __tts_config_release_client(uid);
1085                 __tts_config_release_engine();
1086                 return TTS_CONFIG_ERROR_ENGINE_NOT_FOUND;
1087         }
1088
1089         __tts_config_mgr_print_engine_info();
1090
1091         if (0 != tts_parser_load_config(&g_config_info)) {
1092                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to parse configure information");
1093                 __tts_config_release_client(uid);
1094                 __tts_config_release_engine();
1095                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
1096         }
1097
1098         /* Check whether engine id is valid */
1099         if (0 != __tts_config_mgr_check_engine_is_valid(g_config_info->engine_id)) {
1100                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get default engine");
1101                 __tts_config_release_client(uid);
1102                 __tts_config_release_engine();
1103                 tts_parser_unload_config(g_config_info);
1104                 return TTS_CONFIG_ERROR_ENGINE_NOT_FOUND;
1105         }
1106
1107         if (true == g_config_info->auto_voice) {
1108                 /* Check language with display language */
1109                 __tts_config_set_auto_language();
1110         } else {
1111                 if (false == __tts_config_mgr_check_lang_is_valid(g_config_info->engine_id, g_config_info->language, g_config_info->type)) {
1112                         /* Default language is not valid */
1113                         char* tmp_language = NULL;
1114                         int tmp_type = -1;
1115                         if (0 != __tts_config_mgr_select_lang(g_config_info->engine_id, &tmp_language, &tmp_type)) {
1116                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to select language");
1117                                 __tts_config_release_client(uid);
1118                                 __tts_config_release_engine();
1119                                 tts_parser_unload_config(g_config_info);
1120                                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
1121                         }
1122
1123                         if (NULL != tmp_language) {
1124                                 if (NULL != g_config_info->language) {
1125                                         free(g_config_info->language);
1126                                         g_config_info->language = strdup(tmp_language);
1127                                 }
1128
1129                                 g_config_info->type = tmp_type;
1130
1131                                 free(tmp_language);
1132
1133                                 if (0 != tts_parser_set_voice(g_config_info->language, g_config_info->type)) {
1134                                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to save config");
1135                                         __tts_config_release_client(uid);
1136                                         __tts_config_release_engine();
1137                                         tts_parser_unload_config(g_config_info);
1138                                         return TTS_CONFIG_ERROR_OPERATION_FAILED;
1139                                 }
1140                         }
1141                 }
1142         }
1143
1144         /* print daemon config */
1145         SLOG(LOG_DEBUG, tts_tag(), "== TTS config ==");
1146         SECURE_SLOG(LOG_DEBUG, tts_tag(), " engine : %s", g_config_info->engine_id);
1147         SECURE_SLOG(LOG_DEBUG, tts_tag(), " setting : %s", g_config_info->setting);
1148         SECURE_SLOG(LOG_DEBUG, tts_tag(), " auto voice : %s", g_config_info->auto_voice ? "on" : "off");
1149         SECURE_SLOG(LOG_DEBUG, tts_tag(), " language : %s", g_config_info->language);
1150         SECURE_SLOG(LOG_DEBUG, tts_tag(), " voice type : %d", g_config_info->type);
1151         SECURE_SLOG(LOG_DEBUG, tts_tag(), " speech rate : %d", g_config_info->speech_rate);
1152         SECURE_SLOG(LOG_DEBUG, tts_tag(), " pitch : %d", g_config_info->pitch);
1153         SLOG(LOG_DEBUG, tts_tag(), "=================");
1154
1155         if (0 != __tts_config_mgr_register_config_event()) {
1156                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to register config event");
1157                 __tts_config_release_client(uid);
1158                 __tts_config_release_engine();
1159                 tts_parser_unload_config(g_config_info);
1160                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
1161         }
1162
1163         /* Register to detect display language change */
1164         vconf_notify_key_changed(TTS_LANGSET_KEY, __tts_config_display_language_changed_cb, NULL);
1165         vconf_notify_key_changed(TTS_ACCESSIBILITY_KEY, __tts_config_screen_reader_changed_cb, NULL);
1166
1167         /* For engine directory monitoring */
1168         //if (0 != __tts_config_mgr_register_engine_config_updated_event()) {
1169         //      SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to register engine config updated event");
1170         //      __tts_config_release_client(uid);
1171         //      __tts_config_release_engine();
1172         //      tts_parser_unload_config(g_config_info);
1173         //      __tts_config_mgr_unregister_config_event();
1174         //      return TTS_CONFIG_ERROR_OPERATION_FAILED;
1175         //}
1176
1177         return 0;
1178 }
1179
1180 int tts_config_mgr_finalize(int uid)
1181 {
1182         if (0 < __tts_config_release_client(uid)) {
1183                 return 0;
1184         }
1185
1186         tts_config_mgr_unset_callback(uid);
1187
1188         __tts_config_release_engine();
1189
1190         tts_parser_unload_config(g_config_info);
1191
1192         __tts_config_mgr_unregister_engine_config_updated_event();
1193
1194         __tts_config_mgr_unregister_config_event();
1195
1196         vconf_ignore_key_changed(TTS_LANGSET_KEY, __tts_config_display_language_changed_cb);
1197         vconf_ignore_key_changed(TTS_ACCESSIBILITY_KEY, __tts_config_screen_reader_changed_cb);
1198
1199         return 0;
1200 }
1201
1202 int tts_config_mgr_set_callback(int uid, 
1203                                 tts_config_engine_changed_cb engine_cb, 
1204                                 tts_config_voice_changed_cb voice_cb, 
1205                                 tts_config_speech_rate_changed_cb speech_cb, 
1206                                 tts_config_pitch_changed_cb pitch_cb,
1207                                 void* user_data)
1208 {
1209         GSList *iter = NULL;
1210         tts_config_client_s* temp_client = NULL;
1211
1212         /* Call all callbacks of client*/
1213         iter = g_slist_nth(g_config_client_list, 0);
1214
1215         while (NULL != iter) {
1216                 temp_client = iter->data;
1217
1218                 if (NULL != temp_client) {
1219                         if (uid == temp_client->uid) {
1220                                 temp_client->engine_cb = engine_cb;
1221                                 temp_client->voice_cb = voice_cb;
1222                                 temp_client->speech_cb = speech_cb;
1223                                 temp_client->pitch_cb = pitch_cb;
1224                                 temp_client->user_data = user_data;
1225                         }
1226                 }
1227
1228                 iter = g_slist_next(iter);
1229         }
1230         return 0;
1231 }
1232
1233 int tts_config_mgr_unset_callback(int uid)
1234 {
1235         GSList *iter = NULL;
1236         tts_config_client_s* temp_client = NULL;
1237
1238         /* Call all callbacks of client*/
1239         iter = g_slist_nth(g_config_client_list, 0);
1240
1241         while (NULL != iter) {
1242                 temp_client = iter->data;
1243
1244                 if (NULL != temp_client) {
1245                         if (uid == temp_client->uid) {
1246                                 temp_client->engine_cb = NULL;
1247                                 temp_client->voice_cb = NULL;
1248                                 temp_client->speech_cb = NULL;
1249                                 temp_client->pitch_cb = NULL;
1250                                 temp_client->user_data = NULL;
1251                         }
1252                 }
1253
1254                 iter = g_slist_next(iter);
1255         }
1256
1257         return 0;
1258 }
1259
1260 int tts_config_set_screen_reader_callback(int uid, tts_config_screen_reader_changed_cb callback)
1261 {
1262         if (NULL == callback) {
1263                 SLOG(LOG_ERROR, tts_tag(), "Input parameter is NULL");
1264                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1265         }
1266
1267         GSList *iter = NULL;
1268         tts_config_client_s* temp_client = NULL;
1269
1270         /* Call all callbacks of client*/
1271         iter = g_slist_nth(g_config_client_list, 0);
1272
1273         while (NULL != iter) {
1274                 temp_client = iter->data;
1275
1276                 if (NULL != temp_client) {
1277                         if (uid == temp_client->uid) {
1278                                 temp_client->screen_cb = callback;
1279                         }
1280                 }
1281
1282                 iter = g_slist_next(iter);
1283         }
1284         return 0;
1285 }
1286
1287 int tts_config_unset_screen_reader_callback(int uid)
1288 {
1289         GSList *iter = NULL;
1290         tts_config_client_s* temp_client = NULL;
1291
1292         /* Call all callbacks of client*/
1293         iter = g_slist_nth(g_config_client_list, 0);
1294
1295         while (NULL != iter) {
1296                 temp_client = iter->data;
1297
1298                 if (NULL != temp_client) {
1299                         if (uid == temp_client->uid) {
1300                                 temp_client->screen_cb = NULL;
1301                         }
1302                 }
1303
1304                 iter = g_slist_next(iter);
1305         }
1306         return 0;
1307 }
1308
1309
1310 int tts_config_mgr_get_engine_list(tts_config_supported_engine_cb callback, void* user_data)
1311 {
1312         if (0 >= g_slist_length(g_config_client_list)) {
1313                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1314                 return TTS_CONFIG_ERROR_INVALID_STATE;
1315         }
1316
1317         GSList *iter = NULL;
1318         tts_engine_info_s *engine_info = NULL;
1319
1320         if (0 >= g_slist_length(g_engine_list)) {
1321                 SLOG(LOG_ERROR, tts_tag(), "There is no engine!!");
1322                 return TTS_CONFIG_ERROR_ENGINE_NOT_FOUND;
1323         }
1324
1325         /* Get a first item */
1326         iter = g_slist_nth(g_engine_list, 0);
1327
1328         while (NULL != iter) {
1329                 engine_info = iter->data;
1330
1331                 if (NULL != engine_info) {
1332                         if (false == callback(engine_info->uuid, engine_info->name, engine_info->setting, user_data)) {
1333                                 break;
1334                         }
1335                 }
1336
1337                 iter = g_slist_next(iter);
1338         }
1339
1340         return 0;
1341 }
1342
1343 int tts_config_mgr_get_engine(char** engine)
1344 {
1345         if (0 >= g_slist_length(g_config_client_list)) {
1346                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1347                 return TTS_CONFIG_ERROR_INVALID_STATE;
1348         }
1349
1350         if (NULL == engine) {
1351                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
1352                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1353         }
1354
1355         if (NULL != g_config_info->engine_id) {
1356                 /* Check engine id is valid */
1357                 GSList *iter = NULL;
1358                 tts_engine_info_s *engine_info = NULL;
1359
1360                 if (0 >= g_slist_length(g_engine_list)) {
1361                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] There is no engine!!");
1362                         return TTS_CONFIG_ERROR_ENGINE_NOT_FOUND;
1363                 }
1364
1365                 /* Get a first item */
1366                 iter = g_slist_nth(g_engine_list, 0);
1367
1368                 while (NULL != iter) {
1369                         engine_info = iter->data;
1370
1371                         if (NULL != engine_info) {
1372                                 if (0 == strcmp(engine_info->uuid, g_config_info->engine_id)) {
1373                                         *engine = strdup(g_config_info->engine_id);
1374                                         return 0;
1375                                 }
1376                         }
1377                         iter = g_slist_next(iter);
1378                 }
1379
1380                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Current engine id is not valid");
1381         } else {
1382                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Engine id is NULL");
1383         }
1384
1385         return TTS_CONFIG_ERROR_OPERATION_FAILED;
1386 }
1387
1388 int tts_config_mgr_set_engine(const char* engine)
1389 {
1390         if (0 >= g_slist_length(g_config_client_list)) {
1391                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1392                 return TTS_CONFIG_ERROR_INVALID_STATE;
1393         }
1394
1395         if (NULL == engine)
1396                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1397
1398         /* Check current engine id with new engine id */
1399         if (NULL != g_config_info->engine_id) {
1400                 if (0 == strcmp(g_config_info->engine_id, engine))
1401                         return 0;
1402         }
1403
1404         if (0 >= g_slist_length(g_engine_list)) {
1405                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] There is no engine!!");
1406                 return TTS_CONFIG_ERROR_ENGINE_NOT_FOUND;
1407         }
1408
1409         SLOG(LOG_DEBUG, tts_tag(), "New engine id : %s", engine);
1410
1411         GSList *iter = NULL;
1412         tts_engine_info_s *engine_info = NULL;
1413         bool is_valid_engine = false;
1414
1415         /* Get a first item */
1416         iter = g_slist_nth(g_engine_list, 0);
1417
1418         while (NULL != iter) {
1419                 engine_info = iter->data;
1420
1421                 if (NULL == engine_info) {
1422                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Engine info is NULL");
1423                         iter = g_slist_next(iter);
1424                         continue;
1425                 }
1426
1427                 /* Check engine id is valid */
1428                 if (0 != strcmp(engine, engine_info->uuid)) {
1429                         iter = g_slist_next(iter);
1430                         continue;
1431                 }
1432
1433                 if (NULL != g_config_info->engine_id)
1434                         free(g_config_info->engine_id);
1435
1436                 g_config_info->engine_id = strdup(engine);
1437
1438                 if (NULL != g_config_info->setting)
1439                         free(g_config_info->setting);
1440
1441                 if (NULL != engine_info->setting)
1442                         g_config_info->setting = strdup(engine_info->setting);
1443
1444                 /* Engine is valid*/
1445                 GSList *iter_voice = NULL;
1446                 tts_config_voice_s* voice = NULL;
1447                 bool is_valid_voice = false;
1448
1449                 /* Get a first item */
1450                 iter_voice = g_slist_nth(engine_info->voices, 0);
1451
1452                 while (NULL != iter_voice) {
1453                         /*Get handle data from list*/
1454                         voice = iter_voice->data;
1455
1456                         if (NULL != voice) {
1457                                 if (NULL == voice->language)
1458                                         continue;
1459                                 SLOG(LOG_DEBUG, tts_tag(), " lang(%s) type(%d)", voice->language, voice->type);
1460
1461                                 if (0 == strcmp(voice->language, g_config_info->language)) {
1462                                         if (voice->type == g_config_info->type) {
1463                                                 /* language is valid */
1464                                                 is_valid_voice = true;
1465                                                 g_config_info->type = voice->type;
1466                                         }
1467                                         break;
1468                                 }
1469                         }
1470
1471                         /*Get next item*/
1472                         iter_voice = g_slist_next(iter_voice);
1473                 }
1474
1475                 if (false == is_valid_voice) {
1476                         if (NULL != g_config_info->language) {
1477                                 free(g_config_info->language);
1478
1479                                 iter_voice = g_slist_nth(engine_info->voices, 0);
1480                                 if (NULL != iter_voice) {
1481                                         voice = iter_voice->data;
1482                                         if (NULL != voice) {
1483                                                 if (NULL != voice->language)
1484                                                         g_config_info->language = strdup(voice->language);
1485                                                 g_config_info->type = voice->type;
1486                                         }
1487                                 }
1488                         }
1489                 }
1490
1491                 is_valid_engine = true;
1492                 break;
1493         }
1494
1495         if (true == is_valid_engine) {
1496                 SLOG(LOG_DEBUG, tts_tag(), "[Config] Engine changed");
1497                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "  Engine : %s", g_config_info->engine_id);
1498                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "  Setting : %s", g_config_info->setting);
1499                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "  Language : %s", g_config_info->language);
1500                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "  Type : %d", g_config_info->type);
1501
1502                 if (0 != tts_parser_set_engine(g_config_info->engine_id, g_config_info->setting,
1503                         g_config_info->language, g_config_info->type)) {
1504                                 SLOG(LOG_ERROR, tts_tag(), " Fail to save config");
1505                                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
1506                 }
1507         } else {
1508                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Engine id is not valid");
1509                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
1510         }
1511
1512         return 0;
1513 }
1514
1515 int tts_config_mgr_get_voice_list(const char* engine_id, tts_config_supported_voice_cb callback, void* user_data)
1516 {
1517         if (0 >= g_slist_length(g_config_client_list)) {
1518                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1519                 return TTS_CONFIG_ERROR_INVALID_STATE;
1520         }
1521
1522         if (0 >= g_slist_length(g_engine_list)) {
1523                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] There is no engine");
1524                 return TTS_CONFIG_ERROR_ENGINE_NOT_FOUND;
1525         }
1526
1527         GSList *iter = NULL;
1528         tts_engine_info_s *engine_info = NULL;
1529
1530         /* Get a first item */
1531         iter = g_slist_nth(g_engine_list, 0);
1532
1533         while (NULL != iter) {
1534                 engine_info = iter->data;
1535
1536                 if (NULL == engine_info) {
1537                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] engine info is NULL");
1538                         return TTS_CONFIG_ERROR_OPERATION_FAILED;
1539                 }
1540
1541                 if (0 != strcmp(engine_id, engine_info->uuid)) {
1542                         iter = g_slist_next(iter);
1543                         continue;
1544                 }
1545
1546                 GSList *iter_voice = NULL;
1547                 tts_config_voice_s* voice = NULL;
1548
1549                 /* Get a first item */
1550                 iter_voice = g_slist_nth(engine_info->voices, 0);
1551
1552                 while (NULL != iter_voice) {
1553                         /*Get handle data from list*/
1554                         voice = iter_voice->data;
1555
1556                         SLOG(LOG_DEBUG, tts_tag(), " lang(%s) type(%d)", voice->language, voice->type);
1557                         if (NULL != voice->language) {
1558                                 if (false == callback(engine_info->uuid, voice->language, voice->type, user_data))
1559                                         break;
1560                         }
1561
1562                         /*Get next item*/
1563                         iter_voice = g_slist_next(iter_voice);
1564                 }
1565                 break;
1566         }
1567
1568         return 0;
1569 }
1570
1571 int tts_config_mgr_get_voice(char** language, int* type)
1572 {
1573         if (0 >= g_slist_length(g_config_client_list)) {
1574                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1575                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1576         }
1577
1578         if (0 >= g_slist_length(g_engine_list)) {
1579                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] There is no engine");
1580                 return TTS_CONFIG_ERROR_ENGINE_NOT_FOUND;
1581         }
1582
1583         if (NULL == language || NULL == type)
1584                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1585
1586         if (NULL != g_config_info->language) {
1587                 *language = strdup(g_config_info->language);
1588                 *type = g_config_info->type;
1589         } else {
1590                 SLOG(LOG_ERROR, tts_tag(), "language is NULL");
1591                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
1592         }
1593
1594         return 0;
1595 }
1596
1597 int tts_config_mgr_set_voice(const char* language, int type)
1598 {
1599         if (0 >= g_slist_length(g_config_client_list)) {
1600                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1601                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1602         }
1603
1604         if (NULL == language) {
1605                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
1606                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1607         }
1608
1609         if (0 >= g_slist_length(g_engine_list)) {
1610                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] There is no engine");
1611                 return TTS_CONFIG_ERROR_ENGINE_NOT_FOUND;
1612         }
1613
1614         /* Check language is valid */
1615         if (NULL != g_config_info->language) {
1616                 if (0 != tts_parser_set_voice(language, type)) {
1617                         SLOG(LOG_ERROR, tts_tag(), "Fail to save default voice");
1618                         return TTS_CONFIG_ERROR_OPERATION_FAILED;
1619                 }
1620                 free(g_config_info->language);
1621                 g_config_info->language = strdup(language);
1622                 g_config_info->type = type;
1623
1624         } else {
1625                 SLOG(LOG_ERROR, tts_tag(), "language is NULL");
1626                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
1627         }
1628
1629         return 0;
1630 }
1631
1632 int tts_config_mgr_get_auto_voice(bool* value)
1633 {
1634         if (0 >= g_slist_length(g_config_client_list)) {
1635                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1636                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1637         }
1638
1639         if (NULL == value)
1640                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1641
1642         *value = g_config_info->auto_voice;
1643
1644         return 0;
1645 }
1646
1647 int tts_config_mgr_set_auto_voice(bool value)
1648 {
1649         if (0 >= g_slist_length(g_config_client_list)) {
1650                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1651                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1652         }
1653
1654         if (g_config_info->auto_voice != value) {
1655                 /* Check language is valid */
1656                 if (0 != tts_parser_set_auto_voice(value)) {
1657                         SLOG(LOG_ERROR, tts_tag(), "Fail to save auto voice option");
1658                         return TTS_CONFIG_ERROR_OPERATION_FAILED;
1659                 }
1660                 g_config_info->auto_voice = value;
1661
1662                 if (true == g_config_info->auto_voice) {
1663                         __tts_config_set_auto_language();
1664                 }
1665         }
1666
1667         return 0;
1668 }
1669
1670 int tts_config_mgr_get_speech_rate(int* value)
1671 {
1672         if (0 >= g_slist_length(g_config_client_list)) {
1673                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1674                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1675         }
1676
1677         if (NULL == value) {
1678                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1679         }
1680
1681         *value = g_config_info->speech_rate;
1682
1683         return 0;
1684 }
1685
1686 int tts_config_mgr_set_speech_rate(int value)
1687 {
1688         if (0 >= g_slist_length(g_config_client_list)) {
1689                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1690                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1691         }
1692
1693         if (TTS_CONFIG_SPEED_MIN <= value && value <= TTS_CONFIG_SPEED_MAX) {
1694                 SLOG(LOG_DEBUG, tts_tag(), "[Config] Set speech rate : %d", value);
1695                 if (0 != tts_parser_set_speech_rate(value)) {
1696                         SLOG(LOG_ERROR, tts_tag(), "Fail to save speech rate");
1697                         return TTS_CONFIG_ERROR_OPERATION_FAILED;
1698                 }
1699
1700                 g_config_info->speech_rate = value;
1701         } else {
1702                 SLOG(LOG_ERROR, tts_tag(), "[Config ERROR] Speech rate is invalid : %d", value);
1703         }
1704
1705         return 0;
1706 }
1707
1708 int tts_config_mgr_get_pitch(int* value)
1709 {
1710         if (0 >= g_slist_length(g_config_client_list)) {
1711                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1712                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1713         }
1714
1715         if (NULL == value) {
1716                 return TTS_CONFIG_ERROR_INVALID_PARAMETER;
1717         }
1718
1719         GSList *iter = NULL;
1720         tts_engine_info_s *engine_info = NULL;
1721
1722         if (0 >= g_slist_length(g_engine_list)) {
1723                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] There is no engine!!");
1724                 return TTS_CONFIG_ERROR_ENGINE_NOT_FOUND;
1725         }
1726
1727         /* Get a first item */
1728         iter = g_slist_nth(g_engine_list, 0);
1729
1730         while (NULL != iter) {
1731                 engine_info = iter->data;
1732
1733                 if (NULL == engine_info) {
1734                         SLOG(LOG_ERROR, tts_tag(), "engine info is NULL");
1735                         return TTS_CONFIG_ERROR_OPERATION_FAILED;
1736                 }
1737
1738                 if (0 != strcmp(g_config_info->engine_id, engine_info->uuid)) {
1739                         iter = g_slist_next(iter);
1740                         continue;
1741                 }
1742
1743                 if (false == engine_info->pitch_support) {
1744                         return TTS_CONFIG_ERROR_NOT_SUPPORTED_FEATURE;
1745                 }  else {
1746                         break;
1747                 }
1748         }
1749
1750         *value = g_config_info->pitch;
1751
1752         return 0;
1753 }
1754
1755 int tts_config_mgr_set_pitch(int value)
1756 {
1757         if (0 >= g_slist_length(g_config_client_list)) {
1758                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1759                 return -1;
1760         }
1761
1762         GSList *iter = NULL;
1763         tts_engine_info_s *engine_info = NULL;
1764
1765         if (0 >= g_slist_length(g_engine_list)) {
1766                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] There is no engine!!");
1767                 return TTS_CONFIG_ERROR_ENGINE_NOT_FOUND;
1768         }
1769
1770         /* Get a first item */
1771         iter = g_slist_nth(g_engine_list, 0);
1772
1773         while (NULL != iter) {
1774                 engine_info = iter->data;
1775
1776                 if (NULL == engine_info) {
1777                         SLOG(LOG_ERROR, tts_tag(), "engine info is NULL");
1778                         return TTS_CONFIG_ERROR_OPERATION_FAILED;
1779                 }
1780
1781                 if (0 != strcmp(g_config_info->engine_id, engine_info->uuid)) {
1782                         iter = g_slist_next(iter);
1783                         continue;
1784                 }
1785
1786                 if (false == engine_info->pitch_support) {
1787                         return TTS_CONFIG_ERROR_NOT_SUPPORTED_FEATURE;
1788                 } else {
1789                         break;
1790                 }
1791         }
1792
1793         if (0 != tts_parser_set_pitch(value)) {
1794                 SLOG(LOG_ERROR, tts_tag(), "Fail to save speech rate");
1795                 return TTS_CONFIG_ERROR_OPERATION_FAILED;
1796         }
1797
1798         g_config_info->pitch = value;
1799
1800         return 0;
1801 }
1802
1803 bool tts_config_check_default_engine_is_valid(const char* engine)
1804 {
1805         if (0 >= g_slist_length(g_config_client_list)) {
1806                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1807                 return -1;
1808         }
1809
1810         if (NULL == engine)
1811                 return false;
1812
1813         if (0 >= g_slist_length(g_engine_list))
1814                 return false;
1815
1816         GSList *iter = NULL;
1817         tts_engine_info_s *engine_info = NULL;
1818
1819         /* Get a first item */
1820         iter = g_slist_nth(g_engine_list, 0);
1821
1822         while (NULL != iter) {
1823                 engine_info = iter->data;
1824
1825                 if (NULL != engine_info) {
1826                         if (0 == strcmp(engine, engine_info->uuid)) {
1827                                 return true;
1828                         }
1829                 }
1830                 iter = g_slist_next(iter);
1831         }
1832
1833         return false;
1834 }
1835
1836 bool tts_config_check_default_voice_is_valid(const char* language, int type)
1837 {
1838         if (0 >= g_slist_length(g_config_client_list)) {
1839                 SLOG(LOG_ERROR, tts_tag(), "Not initialized");
1840                 return -1;
1841         }
1842
1843         if (NULL == language)
1844                 return false;
1845
1846         if (NULL == g_config_info->engine_id) {
1847                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Default engine id is NULL");
1848                 return false;
1849         }
1850
1851         if (0 >= g_slist_length(g_engine_list))
1852                 return false;
1853
1854         GSList *iter = NULL;
1855         tts_engine_info_s *engine_info = NULL;
1856
1857         /* Get a first item */
1858         iter = g_slist_nth(g_engine_list, 0);
1859
1860         while (NULL != iter) {
1861                 engine_info = iter->data;
1862
1863                 if (NULL == engine_info) {
1864                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Engine info is NULL");
1865                         iter = g_slist_next(iter);
1866                         continue;
1867                 }
1868
1869                 if (0 != strcmp(g_config_info->engine_id, engine_info->uuid)) {
1870                         iter = g_slist_next(iter);
1871                         continue;
1872                 }
1873
1874                 GSList *iter_voice = NULL;
1875                 tts_config_voice_s* voice = NULL;
1876
1877                 /* Get a first item */
1878                 iter_voice = g_slist_nth(engine_info->voices, 0);
1879
1880                 while (NULL != iter_voice) {
1881                         voice = iter_voice->data;
1882
1883                         if (0 == strcmp(language, voice->language) && voice->type == type)
1884                                 return true;
1885
1886                         /*Get next item*/
1887                         iter_voice = g_slist_next(iter_voice);
1888                 }
1889
1890                 break;
1891         }
1892
1893         return false;
1894 }
1895
1896
1897 int __tts_config_mgr_print_engine_info()
1898 {
1899         GSList *iter = NULL;
1900         tts_engine_info_s *engine_info = NULL;
1901
1902         if (0 >= g_slist_length(g_engine_list)) {
1903                 SLOG(LOG_DEBUG, tts_tag(), "-------------- engine list -----------------");
1904                 SLOG(LOG_DEBUG, tts_tag(), "  No Engine in engine directory");
1905                 SLOG(LOG_DEBUG, tts_tag(), "--------------------------------------------");
1906                 return 0;
1907         }
1908
1909         /* Get a first item */
1910         iter = g_slist_nth(g_engine_list, 0);
1911
1912         SLOG(LOG_DEBUG, tts_tag(), "--------------- engine list -----------------");
1913
1914         int i = 1;
1915         while (NULL != iter) {
1916                 engine_info = iter->data;
1917
1918                 SLOG(LOG_DEBUG, tts_tag(), "[%dth]", i);
1919                 SLOG(LOG_DEBUG, tts_tag(), " name : %s", engine_info->name);
1920                 SLOG(LOG_DEBUG, tts_tag(), " id   : %s", engine_info->uuid);
1921                 SLOG(LOG_DEBUG, tts_tag(), " setting : %s", engine_info->setting);
1922
1923                 SLOG(LOG_DEBUG, tts_tag(), " Voices");
1924                 GSList *iter_voice = NULL;
1925                 tts_config_voice_s* voice = NULL;
1926
1927                 if (g_slist_length(engine_info->voices) > 0) {
1928                         /* Get a first item */
1929                         iter_voice = g_slist_nth(engine_info->voices, 0);
1930
1931                         int j = 1;
1932                         while (NULL != iter_voice) {
1933                                 /*Get handle data from list*/
1934                                 voice = iter_voice->data;
1935
1936                                 SLOG(LOG_DEBUG, tts_tag(), "  [%dth] lang(%s) type(%d)", j, voice->language, voice->type);
1937
1938                                 /*Get next item*/
1939                                 iter_voice = g_slist_next(iter_voice);
1940                                 j++;
1941                         }
1942                 } else {
1943                         SLOG(LOG_ERROR, tts_tag(), "  Voice is NONE");
1944                 }
1945                 iter = g_slist_next(iter);
1946                 i++;
1947         }
1948         SLOG(LOG_DEBUG, tts_tag(), "--------------------------------------------");
1949
1950         return 0;
1951 }