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