Change internal function to static
[platform/core/uifw/tts.git] / common / tts_config_parser.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 <dlog.h>
15 #include <stdio.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18 #include <vconf.h>
19
20 #include "tts_config_parser.h"
21 #include "tts_defs.h"
22
23
24 #define TTS_TAG_ENGINE_BASE_TAG         "tts-engine"
25 #define TTS_TAG_ENGINE_NAME             "name"
26 #define TTS_TAG_ENGINE_ID               "id"
27 #define TTS_TAG_ENGINE_SETTING          "setting"
28 #define TTS_TAG_ENGINE_VOICE_SET        "voices"
29 #define TTS_TAG_ENGINE_VOICE            "voice"
30 #define TTS_TAG_ENGINE_VOICE_TYPE       "type"
31 #define TTS_TAG_ENGINE_PITCH_SUPPORT    "pitch-support"
32 #define TTS_TAG_ENGINE_TEXT_SIZE        "text-size"
33
34 #define TTS_TAG_CONFIG_BASE_TAG         "tts-config"
35 #define TTS_TAG_CONFIG_ENGINE_ID        "engine"
36 #define TTS_TAG_CONFIG_ENGINE_SETTING   "engine-setting"
37 #define TTS_TAG_CONFIG_AUTO_VOICE       "auto"
38 #define TTS_TAG_CONFIG_VOICE_TYPE       "voice-type"
39 #define TTS_TAG_CONFIG_LANGUAGE         "language"
40 #define TTS_TAG_CONFIG_SPEECH_RATE      "speech-rate"
41 #define TTS_TAG_CONFIG_PITCH            "pitch"
42 #define TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO          "background-volume-ratio"
43 #define TTS_TAG_VOICE_TYPE_FEMALE       "female"
44 #define TTS_TAG_VOICE_TYPE_MALE         "male"
45 #define TTS_TAG_VOICE_TYPE_CHILD        "child"
46
47 #define TTS_MAX_TEXT_SIZE       2000
48
49 static xmlDocPtr g_config_doc = NULL;
50 char g_engine_id[128] = {0,};
51 char g_setting[128] = {0,};
52 char g_language[128] = {0,};
53
54 int tts_parser_get_engine_info(const char* path, tts_engine_info_s** engine_info)
55 {
56         if (NULL == path || NULL == engine_info) {
57                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
58                 return -1;
59         }
60
61         bool isTextsize = false;
62         xmlDocPtr doc = NULL;
63         xmlNodePtr cur = NULL;
64         xmlChar *key = NULL;
65         xmlChar *attr = NULL;
66
67         if (0 == access(path, F_OK)) {
68                 SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] Success to access to %s", path);
69                 doc = xmlParseFile(path);
70                 if (doc == NULL) {
71                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse xml file");
72                         return -1;
73                 }
74         } else {
75                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", path);
76                 return -1;
77         }
78
79         cur = xmlDocGetRootElement(doc);
80         if (cur == NULL) {
81                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document. doc path(%s, %p)", path, doc);
82                 xmlFreeDoc(doc);
83                 doc = NULL;
84                 return -1;
85         }
86
87         if (xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_BASE_TAG)) {
88                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT 'tts-engine'. doc path(%s, %p)", path, doc);
89                 xmlFreeDoc(doc);
90                 doc = NULL;
91                 return -1;
92         }
93
94         cur = cur->xmlChildrenNode;
95         if (cur == NULL) {
96                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document. doc path(%s, %p)", path, doc);
97                 xmlFreeDoc(doc);
98                 doc = NULL;
99                 return -1;
100         }
101
102         /* alloc engine info */
103         tts_engine_info_s* temp;
104         temp = (tts_engine_info_s*)calloc(1, sizeof(tts_engine_info_s));
105         if (NULL == temp) {
106                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Out of memory. doc path(%s, %p)", path, doc);
107                 xmlFreeDoc(doc);
108                 doc = NULL;
109                 return -1;
110         }
111
112         temp->name = NULL;
113         temp->uuid = NULL;
114         temp->voices = NULL;
115         temp->setting = NULL;
116         temp->pitch_support = false;
117         temp->text_size = 0;
118
119         while (cur != NULL) {
120                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_NAME)) {
121                         key = xmlNodeGetContent(cur);
122                         if (NULL != key) {
123                                 if (NULL != temp->name) {
124                                         free(temp->name);
125                                         temp->name = NULL;
126                                 }
127                                 temp->name = strdup((char*)key);
128                                 xmlFree(key);
129                                 key = NULL;
130                         } else {
131                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_NAME);
132                         }
133                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_ID)) {
134                         key = xmlNodeGetContent(cur);
135                         if (NULL != key) {
136                                 if (NULL != temp->uuid) {
137                                         free(temp->uuid);
138                                         temp->uuid = NULL;
139                                 }
140                                 temp->uuid = strdup((char*)key);
141                                 xmlFree(key);
142                                 key = NULL;
143                         } else {
144                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_ID);
145                         }
146                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_SETTING)) {
147                         key = xmlNodeGetContent(cur);
148                         if (NULL != key) {
149                                 if (NULL != temp->setting) {
150                                         free(temp->setting);
151                                         temp->setting = NULL;
152                                 }
153                                 temp->setting = strdup((char*)key);
154                                 xmlFree(key);
155                                 key = NULL;
156                         } else {
157                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_SETTING);
158                         }
159                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_VOICE_SET)) {
160                         xmlNodePtr voice_node = NULL;
161                         voice_node = cur->xmlChildrenNode;
162
163                         while (NULL != voice_node) {
164                                 if (0 == xmlStrcmp(voice_node->name, (const xmlChar *)TTS_TAG_ENGINE_VOICE)) {
165                                         tts_config_voice_s* temp_voice = (tts_config_voice_s*)calloc(1, sizeof(tts_config_voice_s));
166                                         if (NULL == temp_voice) {
167                                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Out of memory");
168                                                 break;
169                                         }
170
171                                         attr = xmlGetProp(voice_node, (const xmlChar*)TTS_TAG_ENGINE_VOICE_TYPE);
172                                         if (NULL != attr) {
173                                                 if (0 == xmlStrcmp(attr, (const xmlChar *)TTS_TAG_VOICE_TYPE_FEMALE)) {
174                                                         temp_voice->type = (int)TTS_CONFIG_VOICE_TYPE_FEMALE;
175                                                 } else if (0 == xmlStrcmp(attr, (const xmlChar *)TTS_TAG_VOICE_TYPE_MALE)) {
176                                                         temp_voice->type = (int)TTS_CONFIG_VOICE_TYPE_MALE;
177                                                 } else if (0 == xmlStrcmp(attr, (const xmlChar *)TTS_TAG_VOICE_TYPE_CHILD)) {
178                                                         temp_voice->type = (int)TTS_CONFIG_VOICE_TYPE_CHILD;
179                                                 } else {
180                                                         temp_voice->type = (int)TTS_CONFIG_VOICE_TYPE_USER_DEFINED;
181                                                 }
182                                                 xmlFree(attr);
183                                                 attr = NULL;
184                                         } else {
185                                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_VOICE_TYPE);
186                                                 free(temp_voice);
187                                                 temp_voice = NULL;
188                                                 continue;
189                                         }
190
191                                         key = xmlNodeGetContent(voice_node);
192                                         if (NULL != key) {
193                                                 if (NULL != temp_voice->language) {
194                                                         free(temp_voice->language);
195                                                         temp_voice->language = NULL;
196                                                 }
197                                                 temp_voice->language = strdup((char*)key);
198                                                 xmlFree(key);
199                                                 key = NULL;
200                                                 temp->voices = g_slist_append(temp->voices, temp_voice);
201                                         } else {
202                                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_VOICE);
203                                                 if (NULL != temp_voice) {
204                                                         free(temp_voice);
205                                                         temp_voice = NULL;
206                                                 }
207                                         }
208                                 }
209                                 voice_node = voice_node->next;
210                         }
211                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_PITCH_SUPPORT)) {
212                         key = xmlNodeGetContent(cur);
213                         if (NULL != key) {
214                                 if (0 == xmlStrcmp(key, (const xmlChar *)"true")) {
215                                         temp->pitch_support = true;
216                                 }
217                                 xmlFree(key);
218                                 key = NULL;
219                         } else {
220                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_PITCH_SUPPORT);
221                         }
222                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_TEXT_SIZE)) {
223                         isTextsize = true;
224                         key = xmlNodeGetContent(cur);
225                         if (NULL != key) {
226                                 temp->text_size = atoi((char*)key);
227                                 xmlFree(key);
228                         } else {
229                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[INFO] text size is unlimited.");
230                                 temp->text_size = 0;
231                         }
232                 }
233                 cur = cur->next;
234         }
235
236         if (false == isTextsize) {
237                 temp->text_size = TTS_MAX_TEXT_SIZE;
238         }
239
240         if (NULL != doc) {
241                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] doc path(%s, %p)", path, doc);
242                 xmlFreeDoc(doc);
243                 doc = NULL;
244         }
245
246         if (NULL == temp->uuid) {
247                 /* Invalid engine */
248                 SECURE_SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Invalid engine : %s", path);
249                 tts_parser_free_engine_info(temp);
250                 return -1;
251         }
252
253         *engine_info = temp;
254
255         return 0;
256 }
257
258 int tts_parser_free_engine_info(tts_engine_info_s* engine_info)
259 {
260         if (NULL == engine_info) {
261                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
262                 return -1;
263         }
264
265         if (NULL != engine_info->name) {
266                 free(engine_info->name);
267                 engine_info->name = NULL;
268         }
269         if (NULL != engine_info->uuid) {
270                 free(engine_info->uuid);
271                 engine_info->uuid = NULL;
272         }
273         if (NULL != engine_info->setting) {
274                 free(engine_info->setting);
275                 engine_info->setting = NULL;
276         }
277
278         tts_config_voice_s *temp_voice;
279         temp_voice = g_slist_nth_data(engine_info->voices, 0);
280
281         while (NULL != temp_voice) {
282                 if (NULL != temp_voice) {
283                         if (NULL != temp_voice->language) {
284                                 free(temp_voice->language);
285                                 temp_voice->language = NULL;
286                         }
287                         engine_info->voices = g_slist_remove(engine_info->voices, temp_voice);
288                         free(temp_voice);
289                         temp_voice = NULL;
290                 }
291
292                 temp_voice = g_slist_nth_data(engine_info->voices, 0);
293         }
294
295         if (NULL != engine_info) {
296                 free(engine_info);
297                 engine_info = NULL;
298         }
299
300         return 0;
301 }
302
303 int tts_parser_print_engine_info(tts_engine_info_s* engine_info)
304 {
305         if (NULL == engine_info) {
306                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
307                 return -1;
308         }
309
310         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "== get engine info ==");
311         SLOG(LOG_DEBUG, TAG_TTSCONFIG, " name : %s", engine_info->name);
312         SLOG(LOG_DEBUG, TAG_TTSCONFIG, " id   : %s", engine_info->uuid);
313         if (NULL != engine_info->setting)
314                 SLOG(LOG_DEBUG, TAG_TTSCONFIG, " setting : %s", engine_info->setting);
315
316         SLOG(LOG_DEBUG, TAG_TTSCONFIG, " voices");
317         GSList *iter = NULL;
318         tts_config_voice_s *temp_voice;
319
320         if (g_slist_length(engine_info->voices) > 0) {
321                 /* Get a first item */
322                 iter = g_slist_nth(engine_info->voices, 0);
323
324                 int i = 1;
325                 while (NULL != iter) {
326                         /*Get handle data from list*/
327                         temp_voice = iter->data;
328
329                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "  [%dth] type(%d) lang(%s)", 
330                                 i, temp_voice->type, temp_voice->language);
331
332                         /*Get next item*/
333                         iter = g_slist_next(iter);
334                         i++;
335                 }
336         } else {
337                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "  Voice is NONE");
338         }
339
340         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "@@@");
341
342         return 0;
343 }
344
345 int tts_parser_load_config(tts_config_s** config_info)
346 {
347         if (NULL == config_info) {
348                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
349                 return -1;
350         }
351
352         xmlDocPtr doc = NULL;
353         xmlNodePtr cur = NULL;
354         xmlChar *key;
355         bool is_default_open = false;
356
357         /* For Thread safety */
358         xmlInitParser();
359
360         if (0 != access(TTS_CONFIG, F_OK)) {
361                 doc = xmlParseFile(TTS_DEFAULT_CONFIG);
362                 if (doc == NULL) {
363                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", TTS_DEFAULT_CONFIG);
364                         xmlCleanupParser();
365                         return -1;
366                 }
367                 is_default_open = true;
368         } else {
369                 int retry_count = 0;
370
371                 while (NULL == doc) {
372                         doc = xmlParseFile(TTS_CONFIG);
373                         if (NULL != doc) {
374                                 break;
375                         }
376                         retry_count++;
377                         usleep(10000);
378
379                         if (TTS_RETRY_COUNT == retry_count) {
380                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", TTS_CONFIG);
381                                 doc = xmlParseFile(TTS_DEFAULT_CONFIG);
382                                 if (NULL == doc) {
383                                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", TTS_DEFAULT_CONFIG);
384                                         xmlCleanupParser();
385                                         return -1;
386                                 }
387                                 is_default_open = true;
388                                 break;
389                         }
390                 }
391         }
392
393         cur = xmlDocGetRootElement(doc);
394         if (cur == NULL) {
395                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document(%p)", doc);
396                 xmlFreeDoc(doc);
397                 doc = NULL;
398                 xmlCleanupParser();
399                 return -1;
400         }
401
402         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
403                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s. doc(%p)", TTS_TAG_CONFIG_BASE_TAG, doc);
404                 xmlFreeDoc(doc);
405                 doc = NULL;
406                 xmlCleanupParser();
407                 return -1;
408         }
409
410         cur = cur->xmlChildrenNode;
411         if (cur == NULL) {
412                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document(%p)", doc);
413                 xmlFreeDoc(doc);
414                 doc = NULL;
415                 xmlCleanupParser();
416                 return -1;
417         }
418
419         /* alloc engine info */
420         tts_config_s* temp;
421         temp = (tts_config_s*)calloc(1, sizeof(tts_config_s));
422         if (NULL == temp) {
423                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Out of memory(%p)", doc);
424                 xmlFreeDoc(doc);
425                 doc = NULL;
426                 xmlCleanupParser();
427                 return -1;
428         }
429
430         memset(g_engine_id, '\0', sizeof(g_engine_id));
431         memset(g_setting, '\0', sizeof(g_setting));
432         memset(g_language, '\0', sizeof(g_language));
433
434         temp->engine_id = g_engine_id;
435         temp->setting = g_setting;
436         temp->language = g_language;
437
438         while (cur != NULL) {
439                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_ENGINE_ID)) {
440                         key = xmlNodeGetContent(cur);
441                         if (NULL != key) {
442                                 strncpy(temp->engine_id, (char*)key, sizeof(g_engine_id) - 1);
443                                 xmlFree(key);
444                                 key = NULL;
445                         } else {
446                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] engine id is NULL");
447                         }
448                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_ENGINE_SETTING)) {
449                         key = xmlNodeGetContent(cur);
450                         if (NULL != key) {
451                                 strncpy(temp->setting, (char*)key, sizeof(g_setting) - 1);
452                                 xmlFree(key);
453                                 key = NULL;
454                         } else {
455                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] setting path is NULL");
456                         }
457                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_AUTO_VOICE)) {
458                         key = xmlNodeGetContent(cur);
459                         if (NULL != key) {
460                                 if (0 == xmlStrcmp(key, (const xmlChar *)"on")) {
461                                         temp->auto_voice = true;
462                                 } else if (0 == xmlStrcmp(key, (const xmlChar *)"off")) {
463                                         temp->auto_voice = false;
464                                 } else {
465                                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "Auto voice is wrong");
466                                         temp->auto_voice = true;
467                                 }
468
469                                 xmlFree(key);
470                                 key = NULL;
471                         } else {
472                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] voice type is NULL");
473                         }
474                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_VOICE_TYPE)) {
475                         key = xmlNodeGetContent(cur);
476                         if (NULL != key) {
477                                 if (0 == xmlStrcmp(key, (const xmlChar *)TTS_TAG_VOICE_TYPE_MALE)) {
478                                         temp->type = (int)TTS_CONFIG_VOICE_TYPE_MALE;
479                                 } else if (0 == xmlStrcmp(key, (const xmlChar *)TTS_TAG_VOICE_TYPE_FEMALE)) {
480                                         temp->type = (int)TTS_CONFIG_VOICE_TYPE_FEMALE;
481                                 } else if (0 == xmlStrcmp(key, (const xmlChar *)TTS_TAG_VOICE_TYPE_CHILD)) {
482                                         temp->type = (int)TTS_CONFIG_VOICE_TYPE_CHILD;
483                                 } else {
484                                         SLOG(LOG_WARN, TAG_TTSCONFIG, "Voice type is user defined");
485                                         temp->type = (int)TTS_CONFIG_VOICE_TYPE_USER_DEFINED;
486                                 }
487
488                                 xmlFree(key);
489                                 key = NULL;
490                         } else {
491                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] voice type is NULL");
492                         }
493                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_LANGUAGE)) {
494                         key = xmlNodeGetContent(cur);
495                         if (NULL != key) {
496                                 strncpy(temp->language, (char*)key, sizeof(g_language) - 1);
497                                 xmlFree(key);
498                                 key = NULL;
499                         } else {
500                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] engine uuid is NULL");
501                         }
502
503                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_SPEECH_RATE)) {
504                         key = xmlNodeGetContent(cur);
505                         if (NULL != key) {
506                                 temp->speech_rate = atoi((char*)key);
507                                 xmlFree(key);
508                         } else {
509                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] speech rate is NULL");
510                         }
511                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_PITCH)) {
512                         key = xmlNodeGetContent(cur);
513                         if (NULL != key) {
514                                 temp->pitch = atoi((char*)key);
515                                 xmlFree(key);
516                                 key = NULL;
517                         } else {
518                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Pitch is NULL");
519                         }
520                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO)) {
521                         key = xmlNodeGetContent(cur);
522                         if (NULL != key) {
523                                 temp->bg_volume_ratio = atof((char*)key);
524                                 xmlFree(key);
525                                 key = NULL;
526                         } else {
527                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Background volume ratio is NULL");
528                         }
529                 } else {
530
531                 }
532
533                 cur = cur->next;
534         }
535
536         *config_info = temp;
537         g_config_doc = doc;
538
539         if (true == is_default_open) {
540                 int retry_count = 0;
541                 int ret = -1;
542                 do {
543                         ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
544                         if (0 < ret)
545                                 break;
546                         retry_count++;
547                         usleep(10000);
548
549                         if (TTS_RETRY_COUNT == retry_count) {
550                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
551                                 return -1;
552                         }
553                 } while (0 != ret);
554
555                 /* Set mode */
556                 if (0 > chmod(TTS_CONFIG, 0600)) {
557                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to change file mode : %d", ret);
558                 }
559
560                 /* Set owner */
561                 if (0 > chown(TTS_CONFIG, 5000, 5000)) {
562                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to change file owner : %d", ret);
563                 }
564                 SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Default config is changed : pid(%d)", getpid());
565         }
566
567         return 0;
568 }
569
570 int tts_parser_unload_config(tts_config_s* config_info)
571 {
572         if (NULL != g_config_doc) {
573                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Free g_config_doc(%p)", g_config_doc);
574                 xmlFreeDoc(g_config_doc);
575                 g_config_doc = NULL;
576         }
577         if (NULL != config_info) {
578                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Free config_info(%p)", config_info);
579                 free(config_info);
580                 config_info = NULL;
581         }
582
583         xmlCleanupParser();
584
585         return 0;
586 }
587
588
589 int tts_parser_copy_xml(const char* original, const char* destination)
590 {
591         if (NULL == original || NULL == destination) {
592                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
593                 return -1;
594         }
595
596         xmlDocPtr doc = NULL;
597         if (0 == access(original, F_OK)) {
598                 SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] Success to access to %s", original);
599                 doc = xmlParseFile(original);
600                 if (doc == NULL) {
601                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", original);
602                         return -1;
603                 }
604         } else {
605                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", original);
606                 return -1;
607         }
608
609         int ret = xmlSaveFile(destination, doc);
610         if (0 > ret) {
611                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
612         } else {
613                 static FILE* pFile;
614                 pFile = fopen(destination, "r");
615                 int fd = -1;
616                 if (NULL == pFile) {
617                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", destination);
618                 } else {
619                         fd = fileno(pFile);
620                         fsync(fd);
621                         fclose(pFile);
622                         SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", destination);
623                 }
624                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", destination);
625         }
626
627         /* Set mode */
628         if (0 > chmod(destination, 0600)) {
629                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to change file mode : %d", ret);
630         }
631
632         if (NULL != doc) {
633                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] doc(%p)", doc);
634                 xmlFreeDoc(doc);
635                 doc = NULL;
636         }
637
638         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[SUCCESS] Copying xml");
639
640         return 0;
641 }
642
643 int tts_parser_set_engine(const char* engine_id, const char* setting, const char* language, int type)
644 {
645         if (NULL == engine_id) {
646                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
647                 return -1;
648         }
649
650         xmlNodePtr cur = NULL;
651         cur = xmlDocGetRootElement(g_config_doc);
652         if (cur == NULL) {
653                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
654                 return -1;
655         }
656
657         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
658                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
659                 return -1;
660         }
661
662         cur = cur->xmlChildrenNode;
663         if (cur == NULL) {
664                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
665                 return -1;
666         }
667
668         while (cur != NULL) {
669                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_ENGINE_ID)) {
670                         xmlNodeSetContent(cur, (const xmlChar *)engine_id);
671                 }
672
673                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_LANGUAGE)) {
674                         xmlNodeSetContent(cur, (const xmlChar *)language);
675                 }
676
677                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_ENGINE_SETTING)) {
678                         xmlNodeSetContent(cur, (const xmlChar *)setting);
679                 }
680
681                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_VOICE_TYPE)) {
682                         switch (type) {
683                         case TTS_CONFIG_VOICE_TYPE_MALE:        xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_MALE);        break;
684                         case TTS_CONFIG_VOICE_TYPE_FEMALE:      xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);      break;
685                         case TTS_CONFIG_VOICE_TYPE_CHILD:       xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_CHILD);       break;
686                         default:                                xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);      break;
687                         }
688                 }
689
690                 cur = cur->next;
691         }
692
693         if (0 == access(TTS_CONFIG, F_OK)) {
694                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
695                 if (0 > ret) {
696                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
697                 } else {
698                         static FILE* pFile;
699                         pFile = fopen(TTS_CONFIG, "r");
700                         int fd = -1;
701                         if (NULL == pFile) {
702                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
703                         } else {
704                                 fd = fileno(pFile);
705                                 fsync(fd);
706                                 fclose(pFile);
707                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
708                         }
709                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
710                 }
711         } else {
712                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
713         }
714
715         return 0;
716 }
717
718 int tts_parser_set_voice(const char* language, int type)
719 {
720         if (NULL == language) {
721                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
722                 return -1;
723         }
724
725         xmlNodePtr cur = NULL;
726         cur = xmlDocGetRootElement(g_config_doc);
727         if (cur == NULL) {
728                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
729                 return -1;
730         }
731
732         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
733                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
734                 return -1;
735         }
736
737         cur = cur->xmlChildrenNode;
738         if (cur == NULL) {
739                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
740                 return -1;
741         }
742
743         while (cur != NULL) {
744                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_LANGUAGE)) {
745                         xmlNodeSetContent(cur, (const xmlChar *)language);
746                 }
747
748                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_VOICE_TYPE)) {
749                         switch (type) {
750                         case TTS_CONFIG_VOICE_TYPE_MALE:        xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_MALE);        break;
751                         case TTS_CONFIG_VOICE_TYPE_FEMALE:      xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);      break;
752                         case TTS_CONFIG_VOICE_TYPE_CHILD:       xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_CHILD);       break;
753                         default:
754                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Invalid type : %d", type);
755                                 xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);
756                                 break;
757                         }
758                 }
759
760                 cur = cur->next;
761         }
762
763         if (0 == access(TTS_CONFIG, F_OK)) {
764                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
765                 if (0 > ret) {
766                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
767                 } else {
768                         static FILE* pFile;
769                         pFile = fopen(TTS_CONFIG, "r");
770                         int fd = -1;
771                         if (NULL == pFile) {
772                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
773                         } else {
774                                 fd = fileno(pFile);
775                                 fsync(fd);
776                                 fclose(pFile);
777                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
778                         }
779                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
780                 }
781         } else {
782                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
783         }
784         return 0;
785 }
786
787 int tts_parser_set_auto_voice(bool value)
788 {
789         xmlNodePtr cur = NULL;
790         cur = xmlDocGetRootElement(g_config_doc);
791         if (cur == NULL) {
792                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
793                 return -1;
794         }
795
796         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
797                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
798                 return -1;
799         }
800
801         cur = cur->xmlChildrenNode;
802         if (cur == NULL) {
803                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
804                 return -1;
805         }
806
807         while (cur != NULL) {
808                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_AUTO_VOICE)) {
809                         if (true == value) {
810                                 xmlNodeSetContent(cur, (const xmlChar *)"on");
811                         } else if (false == value) {
812                                 xmlNodeSetContent(cur, (const xmlChar *)"off");
813                         } else {
814                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong value of auto voice");
815                                 return -1;
816                         }
817                         break;
818                 }
819                 cur = cur->next;
820         }
821
822         if (0 == access(TTS_CONFIG, F_OK)) {
823                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
824                 if (0 > ret) {
825                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
826                 } else {
827                         static FILE* pFile;
828                         pFile = fopen(TTS_CONFIG, "r");
829                         int fd = -1;
830                         if (NULL == pFile) {
831                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
832                         } else {
833                                 fd = fileno(pFile);
834                                 fsync(fd);
835                                 fclose(pFile);
836                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
837                         }
838                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
839                 }
840         } else {
841                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
842         }
843
844         return 0;
845 }
846
847 int tts_parser_set_speech_rate(int value)
848 {
849         xmlNodePtr cur = NULL;
850         cur = xmlDocGetRootElement(g_config_doc);
851         if (cur == NULL) {
852                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
853                 return -1;
854         }
855
856         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
857                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
858                 return -1;
859         }
860
861         cur = cur->xmlChildrenNode;
862         if (cur == NULL) {
863                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
864                 return -1;
865         }
866
867         while (cur != NULL) {
868                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_SPEECH_RATE)) {
869                         char temp[10];
870                         memset(temp, '\0', 10);
871                         snprintf(temp, 10, "%d", value);
872
873                         xmlNodeSetContent(cur, (const xmlChar *)temp);
874
875                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Set speech rate : %s", temp);
876                         break;
877                 }
878
879                 cur = cur->next;
880         }
881
882         if (0 == access(TTS_CONFIG, F_OK)) {
883                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
884                 if (0 > ret) {
885                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
886                 } else {
887                         static FILE* pFile;
888                         pFile = fopen(TTS_CONFIG, "r");
889                         int fd = -1;
890                         if (NULL == pFile) {
891                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
892                         } else {
893                                 fd = fileno(pFile);
894                                 fsync(fd);
895                                 fclose(pFile);
896                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
897                         }
898                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
899                 }
900         } else {
901                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
902         }
903
904         return 0;
905 }
906
907 int tts_parser_set_pitch(int value)
908 {
909         xmlNodePtr cur = NULL;
910         cur = xmlDocGetRootElement(g_config_doc);
911         if (cur == NULL) {
912                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
913                 return -1;
914         }
915
916         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
917                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
918                 return -1;
919         }
920
921         cur = cur->xmlChildrenNode;
922         if (cur == NULL) {
923                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
924                 return -1;
925         }
926
927         while (cur != NULL) {
928                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_PITCH)) {
929                         char temp[10];
930                         memset(temp, '\0', 10);
931                         snprintf(temp, 10, "%d", value);
932                         xmlNodeSetContent(cur, (const xmlChar *)temp);
933                         break;
934                 }
935
936                 cur = cur->next;
937         }
938
939         if (0 == access(TTS_CONFIG, F_OK)) {
940                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
941                 if (0 > ret) {
942                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
943                 } else {
944                         static FILE* pFile;
945                         pFile = fopen(TTS_CONFIG, "r");
946                         int fd = -1;
947                         if (NULL == pFile) {
948                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
949                         } else {
950                                 fd = fileno(pFile);
951                                 fsync(fd);
952                                 fclose(pFile);
953                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
954                         }
955                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
956                 }
957         } else {
958                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
959         }
960
961         return 0;
962 }
963
964 int tts_parser_set_bg_volume_ratio(double value)
965 {
966         xmlNodePtr cur = NULL;
967         cur = xmlDocGetRootElement(g_config_doc);
968         if (cur == NULL) {
969                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
970                 return -1;
971         }
972
973         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
974                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
975                 return -1;
976         }
977
978         cur = cur->xmlChildrenNode;
979         if (cur == NULL) {
980                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
981                 return -1;
982         }
983
984         while (cur != NULL) {
985                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO)) {
986                         char temp[10];
987                         memset(temp, '\0', 10);
988                         snprintf(temp, 10, "%lf", value);
989                         xmlNodeSetContent(cur, (const xmlChar *)temp);
990                         break;
991                 }
992
993                 cur = cur->next;
994         }
995
996         if (0 == access(TTS_CONFIG, F_OK)) {
997                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
998                 if (0 > ret) {
999                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
1000                 } else {
1001                         static FILE* pFile;
1002                         pFile = fopen(TTS_CONFIG, "r");
1003                         int fd = -1;
1004                         if (NULL == pFile) {
1005                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
1006                         } else {
1007                                 fd = fileno(pFile);
1008                                 fsync(fd);
1009                                 fclose(pFile);
1010                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
1011                         }
1012                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
1013                 }
1014         } else {
1015                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
1016         }
1017
1018         return 0;
1019 }
1020
1021 int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voice, char** language, int* voice_type, 
1022                                    int* speech_rate, int* pitch, double* bg_volume_ratio)
1023 {
1024         if (NULL == engine || NULL == setting || NULL == language || NULL == voice_type || NULL == speech_rate) {
1025                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
1026                 return -1;
1027         }
1028
1029         xmlDocPtr doc = NULL;
1030         xmlNodePtr cur_new = NULL;
1031         xmlNodePtr cur_old = NULL;
1032
1033         xmlChar *key_new;
1034         xmlChar *key_old;
1035
1036         int retry_count = 0;
1037         while (NULL == doc) {
1038                 if (0 == access(TTS_CONFIG, F_OK)) {
1039                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] Success to access to %s", TTS_CONFIG);
1040                         doc = xmlParseFile(TTS_CONFIG);
1041                         if (NULL != doc) {
1042                                 break;
1043                         }
1044                 }
1045                 retry_count++;
1046                 usleep(10000);
1047
1048                 if (TTS_RETRY_COUNT == retry_count) {
1049                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", TTS_CONFIG);
1050                         return -1;
1051                 }
1052         }
1053
1054         cur_new = xmlDocGetRootElement(doc);
1055         cur_old = xmlDocGetRootElement(g_config_doc);
1056         if (cur_new == NULL || cur_old == NULL) {
1057                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document(%p)", doc);
1058                 xmlFreeDoc(doc);
1059                 doc = NULL;
1060                 return -1;
1061         }
1062
1063         if (xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_BASE_TAG) || 
1064         xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_BASE_TAG)) {
1065                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s. doc(%p)", TTS_TAG_CONFIG_BASE_TAG, doc);
1066                 xmlFreeDoc(doc);
1067                 doc = NULL;
1068                 return -1;
1069         }
1070
1071         cur_new = cur_new->xmlChildrenNode;
1072         cur_old = cur_old->xmlChildrenNode;
1073         if (cur_new == NULL || cur_old == NULL) {
1074                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document(%p)", doc);
1075                 xmlFreeDoc(doc);
1076                 doc = NULL;
1077                 return -1;
1078         }
1079
1080         while (cur_new != NULL && cur_old != NULL) {
1081                 if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_ID)) {
1082                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_ID)) {
1083                                 key_old = xmlNodeGetContent(cur_old);
1084                                 if (NULL != key_old) {
1085                                         key_new = xmlNodeGetContent(cur_new);
1086                                         if (NULL != key_new) {
1087                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1088                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old engine id(%s), New engine(%s)", 
1089                                                                 (char*)key_old, (char*)key_new);
1090                                                         if (NULL != *engine) {
1091                                                                 free(*engine);
1092                                                                 *engine = NULL;
1093                                                         }
1094                                                         *engine = strdup((char*)key_new);
1095                                                 }
1096                                                 xmlFree(key_new);
1097                                                 key_new = NULL;
1098                                         }
1099                                         xmlFree(key_old);
1100                                         key_old = NULL;
1101                                 }
1102                         } else {
1103                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1104                         }
1105                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_SETTING)) {
1106                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_SETTING)) {
1107                                 key_old = xmlNodeGetContent(cur_old);
1108                                 if (NULL != key_old) {
1109                                         key_new = xmlNodeGetContent(cur_new);
1110                                         if (NULL != key_new) {
1111                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1112                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old engine setting(%s), New engine setting(%s)", 
1113                                                                 (char*)key_old, (char*)key_new);
1114                                                         if (NULL != *setting) {
1115                                                                 free(*setting);
1116                                                                 *setting = NULL;
1117                                                         }
1118                                                         *setting = strdup((char*)key_new);
1119                                                 }
1120                                                 xmlFree(key_new);
1121                                                 key_new = NULL;
1122                                         }
1123                                         xmlFree(key_old);
1124                                         key_old = NULL;
1125                                 }
1126                         } else {
1127                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1128                         }
1129                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_AUTO_VOICE)) {
1130                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_AUTO_VOICE)) {
1131                                 key_old = xmlNodeGetContent(cur_old);
1132                                 if (NULL != key_old) {
1133                                         key_new = xmlNodeGetContent(cur_new);
1134                                         if (NULL != key_new) {
1135                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1136                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old auto voice (%s), New auto voice(%s)", 
1137                                                                 (char*)key_old, (char*)key_new);
1138                                                         if (0 == xmlStrcmp((const xmlChar*)"on", key_new)) {
1139                                                                 *auto_voice = true;
1140                                                         } else {
1141                                                                 *auto_voice = false;
1142                                                         }
1143                                                 }
1144                                                 xmlFree(key_new);
1145                                                 key_new = NULL;
1146                                         }
1147                                         xmlFree(key_old);
1148                                         key_old = NULL;
1149                                 }
1150                         } else {
1151                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1152                         }
1153                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_LANGUAGE)) {
1154                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_LANGUAGE)) {
1155                                 key_old = xmlNodeGetContent(cur_old);
1156                                 if (NULL != key_old) {
1157                                         key_new = xmlNodeGetContent(cur_new);
1158                                         if (NULL != key_new) {
1159                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1160                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old language(%s), New language(%s)", 
1161                                                                 (char*)key_old, (char*)key_new);
1162                                                         if (NULL != *language) {
1163                                                                 free(*language);
1164                                                                 *language = NULL;
1165                                                         }
1166                                                         *language = strdup((char*)key_new);
1167                                                 }
1168                                                 xmlFree(key_new);
1169                                                 key_new = NULL;
1170                                         }
1171                                         xmlFree(key_old);
1172                                         key_old = NULL;
1173                                 }
1174                         } else {
1175                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1176                         }
1177                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_VOICE_TYPE)) {
1178                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_VOICE_TYPE)) {
1179                                 key_old = xmlNodeGetContent(cur_old);
1180                                 if (NULL != key_old) {
1181                                         key_new = xmlNodeGetContent(cur_new);
1182                                         if (NULL != key_new) {
1183                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1184                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old voice type(%s), New voice type(%s)", 
1185                                                                 (char*)key_old, (char*)key_new);
1186                                                         if (0 == xmlStrcmp(key_new, (const xmlChar *)TTS_TAG_VOICE_TYPE_FEMALE)) {
1187                                                                 *voice_type = (int)TTS_CONFIG_VOICE_TYPE_FEMALE;
1188                                                         } else if (0 == xmlStrcmp(key_new, (const xmlChar *)TTS_TAG_VOICE_TYPE_MALE)) {
1189                                                                 *voice_type = (int)TTS_CONFIG_VOICE_TYPE_MALE;
1190                                                         } else if (0 == xmlStrcmp(key_new, (const xmlChar *)TTS_TAG_VOICE_TYPE_CHILD)) {
1191                                                                 *voice_type = (int)TTS_CONFIG_VOICE_TYPE_CHILD;
1192                                                         } else {
1193                                                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] New voice type is not valid");
1194                                                         }
1195                                                 }
1196                                                 xmlFree(key_new);
1197                                                 key_new = NULL;
1198                                         }
1199                                         xmlFree(key_old);
1200                                         key_old = NULL;
1201                                 }
1202                         } else {
1203                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1204                         }
1205                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_SPEECH_RATE)) {
1206                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_SPEECH_RATE)) {
1207                                 key_old = xmlNodeGetContent(cur_old);
1208                                 if (NULL != key_old) {
1209                                         key_new = xmlNodeGetContent(cur_new);
1210                                         if (NULL != key_new) {
1211                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1212                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old speech rate(%s), New speech rate(%s)", 
1213                                                                 (char*)key_old, (char*)key_new);
1214                                                         *speech_rate = atoi((char*)key_new);
1215                                                 }
1216                                                 xmlFree(key_new);
1217                                                 key_new = NULL;
1218                                         }
1219                                         xmlFree(key_old);
1220                                         key_old = NULL;
1221                                 }
1222                         } else {
1223                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1224                         }
1225                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_PITCH)) {
1226                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_PITCH)) {
1227                                 key_old = xmlNodeGetContent(cur_old);
1228                                 if (NULL != key_old) {
1229                                         key_new = xmlNodeGetContent(cur_new);
1230                                         if (NULL != key_new) {
1231                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1232                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old pitch(%s), New pitch(%s)", 
1233                                                                 (char*)key_old, (char*)key_new);
1234                                                         *pitch = atoi((char*)key_new);
1235                                                 }
1236                                                 xmlFree(key_new);
1237                                                 key_new = NULL;
1238                                         }
1239                                         xmlFree(key_old);
1240                                         key_old = NULL;
1241                                 }
1242                         } else {
1243                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1244                         }
1245                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO)) {
1246                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO)) {
1247                                 key_old = xmlNodeGetContent(cur_old);
1248                                 if (NULL != key_old) {
1249                                         key_new = xmlNodeGetContent(cur_new);
1250                                         if (NULL != key_new) {
1251                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1252                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old bg volume ratio(%s), New bg volume ratio(%s)", 
1253                                                                 (char*)key_old, (char*)key_new);
1254                                                         *bg_volume_ratio = atof((char*)key_new);
1255                                                 }
1256                                                 xmlFree(key_new);
1257                                                 key_new = NULL;
1258                                         }
1259                                         xmlFree(key_old);
1260                                         key_old = NULL;
1261                                 }
1262                         } else {
1263                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1264                         }
1265                 } else {
1266
1267                 }
1268
1269                 cur_new = cur_new->next;
1270                 cur_old = cur_old->next;
1271         }
1272
1273         if (NULL != g_config_doc) {
1274                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Free g_config_doc(%p)", g_config_doc);
1275                 xmlFreeDoc(g_config_doc);
1276                 g_config_doc = NULL;
1277         }
1278         g_config_doc = doc;
1279
1280         return 0;
1281 }
1282
1283 int tts_parser_reset()
1284 {
1285         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] Reset g_config_doc as %s", TTS_DEFAULT_CONFIG);
1286
1287         if (NULL != g_config_doc) {
1288                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Free g_config_doc(%p)", g_config_doc);
1289                 xmlFreeDoc(g_config_doc);
1290                 g_config_doc = NULL;
1291         }
1292
1293         g_config_doc = xmlParseFile(TTS_DEFAULT_CONFIG);
1294         if (NULL == g_config_doc) {
1295                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse %s", TTS_DEFAULT_CONFIG);
1296                 return -1;
1297         }
1298
1299         if (0 == access(TTS_CONFIG, F_OK)) {
1300                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
1301                 if (0 > ret) {
1302                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to save %s", TTS_CONFIG);
1303                 } else {
1304                         static FILE* pFile;
1305                         pFile = fopen(TTS_CONFIG, "r");
1306                         int fd = -1;
1307                         if (NULL == pFile) {
1308                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
1309                         } else {
1310                                 fd = fileno(pFile);
1311                                 fsync(fd);
1312                                 fclose(pFile);
1313                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
1314                         }
1315                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
1316                 }
1317         } else {
1318                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
1319         }
1320
1321         return 0;
1322 }