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