Update hello protocol
[platform/core/uifw/tts.git] / common / tts_config_parser.c
index c29a595..51ff971 100644 (file)
@@ -29,6 +29,7 @@
 #define TTS_TAG_ENGINE_VOICE           "voice"
 #define TTS_TAG_ENGINE_VOICE_TYPE      "type"
 #define TTS_TAG_ENGINE_PITCH_SUPPORT   "pitch-support"
+#define TTS_TAG_ENGINE_TEXT_SIZE       "text-size"
 
 #define TTS_TAG_CONFIG_BASE_TAG                "tts-config"
 #define TTS_TAG_CONFIG_ENGINE_ID       "engine"
 #define TTS_TAG_CONFIG_LANGUAGE                "language"
 #define TTS_TAG_CONFIG_SPEECH_RATE     "speech-rate"
 #define TTS_TAG_CONFIG_PITCH           "pitch"
+#define TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO         "background-volume-ratio"
 #define TTS_TAG_VOICE_TYPE_FEMALE      "female"
 #define TTS_TAG_VOICE_TYPE_MALE                "male"
 #define TTS_TAG_VOICE_TYPE_CHILD       "child"
 
-
-extern char* tts_tag();
+#define TTS_MAX_TEXT_SIZE      2000
 
 static xmlDocPtr g_config_doc = NULL;
+char g_engine_id[128] = {0,};
+char g_setting[128] = {0,};
+char g_language[128] = {0,};
 
 int tts_parser_get_engine_info(const char* path, tts_engine_info_s** engine_info)
 {
        if (NULL == path || NULL == engine_info) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
                return -1;
        }
 
+       bool isTextsize = false;
        xmlDocPtr doc = NULL;
        xmlNodePtr cur = NULL;
        xmlChar *key = NULL;
        xmlChar *attr = NULL;
 
-       doc = xmlParseFile(path);
-       if (doc == NULL) {
+       if (0 == access(path, F_OK)) {
+               SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] Success to access to %s", path);
+               doc = xmlParseFile(path);
+               if (doc == NULL) {
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse xml file");
+                       return -1;
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", path);
                return -1;
        }
 
        cur = xmlDocGetRootElement(doc);
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document. doc path(%s, %p)", path, doc);
                xmlFreeDoc(doc);
+               doc = NULL;
                return -1;
        }
 
        if (xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_BASE_TAG)) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT 'tts-engine'");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT 'tts-engine'. doc path(%s, %p)", path, doc);
                xmlFreeDoc(doc);
+               doc = NULL;
                return -1;
        }
 
        cur = cur->xmlChildrenNode;
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document. doc path(%s, %p)", path, doc);
                xmlFreeDoc(doc);
+               doc = NULL;
                return -1;
        }
 
@@ -88,8 +103,9 @@ int tts_parser_get_engine_info(const char* path, tts_engine_info_s** engine_info
        tts_engine_info_s* temp;
        temp = (tts_engine_info_s*)calloc(1, sizeof(tts_engine_info_s));
        if (NULL == temp) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Out of memory");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Out of memory. doc path(%s, %p)", path, doc);
                xmlFreeDoc(doc);
+               doc = NULL;
                return -1;
        }
 
@@ -98,34 +114,47 @@ int tts_parser_get_engine_info(const char* path, tts_engine_info_s** engine_info
        temp->voices = NULL;
        temp->setting = NULL;
        temp->pitch_support = false;
+       temp->text_size = 0;
 
        while (cur != NULL) {
                if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_NAME)) {
                        key = xmlNodeGetContent(cur);
                        if (NULL != key) {
-                               if (NULL != temp->name) free(temp->name);
+                               if (NULL != temp->name) {
+                                       free(temp->name);
+                                       temp->name = NULL;
+                               }
                                temp->name = strdup((char*)key);
                                xmlFree(key);
+                               key = NULL;
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] <%s> has no content", TTS_TAG_ENGINE_NAME);
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_NAME);
                        }
                } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_ID)) {
                        key = xmlNodeGetContent(cur);
                        if (NULL != key) {
-                               if (NULL != temp->uuid) free(temp->uuid);
+                               if (NULL != temp->uuid) {
+                                       free(temp->uuid);
+                                       temp->uuid = NULL;
+                               }
                                temp->uuid = strdup((char*)key);
                                xmlFree(key);
+                               key = NULL;
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] <%s> has no content", TTS_TAG_ENGINE_ID);
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_ID);
                        }
                } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_SETTING)) {
                        key = xmlNodeGetContent(cur);
                        if (NULL != key) {
-                               if (NULL != temp->setting)      free(temp->setting);
+                               if (NULL != temp->setting) {
+                                       free(temp->setting);
+                                       temp->setting = NULL;
+                               }
                                temp->setting = strdup((char*)key);
                                xmlFree(key);
+                               key = NULL;
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] <%s> has no content", TTS_TAG_ENGINE_SETTING);
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_SETTING);
                        }
                } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_VOICE_SET)) {
                        xmlNodePtr voice_node = NULL;
@@ -133,10 +162,9 @@ int tts_parser_get_engine_info(const char* path, tts_engine_info_s** engine_info
 
                        while (NULL != voice_node) {
                                if (0 == xmlStrcmp(voice_node->name, (const xmlChar *)TTS_TAG_ENGINE_VOICE)) {
-
                                        tts_config_voice_s* temp_voice = (tts_config_voice_s*)calloc(1, sizeof(tts_config_voice_s));
                                        if (NULL == temp_voice) {
-                                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Out of memory");
+                                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Out of memory");
                                                break;
                                        }
 
@@ -152,20 +180,29 @@ int tts_parser_get_engine_info(const char* path, tts_engine_info_s** engine_info
                                                        temp_voice->type = (int)TTS_CONFIG_VOICE_TYPE_USER_DEFINED;
                                                }
                                                xmlFree(attr);
+                                               attr = NULL;
                                        } else {
-                                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] <%s> has no content", TTS_TAG_ENGINE_VOICE_TYPE);
+                                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_VOICE_TYPE);
+                                               free(temp_voice);
+                                               temp_voice = NULL;
+                                               continue;
                                        }
 
                                        key = xmlNodeGetContent(voice_node);
                                        if (NULL != key) {
-                                               if (NULL != temp_voice->language)       free(temp_voice->language);
+                                               if (NULL != temp_voice->language) {
+                                                       free(temp_voice->language);
+                                                       temp_voice->language = NULL;
+                                               }
                                                temp_voice->language = strdup((char*)key);
                                                xmlFree(key);
+                                               key = NULL;
                                                temp->voices = g_slist_append(temp->voices, temp_voice);
                                        } else {
-                                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] <%s> has no content", TTS_TAG_ENGINE_VOICE);
+                                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_VOICE);
                                                if (NULL != temp_voice) {
                                                        free(temp_voice);
+                                                       temp_voice = NULL;
                                                }
                                        }
                                }
@@ -178,18 +215,37 @@ int tts_parser_get_engine_info(const char* path, tts_engine_info_s** engine_info
                                        temp->pitch_support = true;
                                }
                                xmlFree(key);
+                               key = NULL;
+                       } else {
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_PITCH_SUPPORT);
+                       }
+               } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_TEXT_SIZE)) {
+                       isTextsize = true;
+                       key = xmlNodeGetContent(cur);
+                       if (NULL != key) {
+                               temp->text_size = atoi((char*)key);
+                               xmlFree(key);
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] <%s> has no content", TTS_TAG_ENGINE_PITCH_SUPPORT);
+                               SLOG(LOG_INFO, TAG_TTSCONFIG, "[INFO] text size is unlimited.");
+                               temp->text_size = 0;
                        }
                }
                cur = cur->next;
        }
 
-       xmlFreeDoc(doc);
+       if (false == isTextsize) {
+               temp->text_size = TTS_MAX_TEXT_SIZE;
+       }
 
-       if (NULL == temp->name || NULL == temp->uuid) {
+       if (NULL != doc) {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] doc path(%s, %p)", path, doc);
+               xmlFreeDoc(doc);
+               doc = NULL;
+       }
+
+       if (NULL == temp->uuid) {
                /* Invalid engine */
-               SECURE_SLOG(LOG_ERROR, tts_tag(), "[ERROR] Invalid engine : %s", path);
+               SECURE_SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Invalid engine : %s", path);
                tts_parser_free_engine_info(temp);
                return -1;
        }
@@ -202,46 +258,62 @@ int tts_parser_get_engine_info(const char* path, tts_engine_info_s** engine_info
 int tts_parser_free_engine_info(tts_engine_info_s* engine_info)
 {
        if (NULL == engine_info) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
                return -1;
        }
 
-       if (NULL != engine_info->name)          free(engine_info->name);
-       if (NULL != engine_info->uuid)          free(engine_info->uuid);
-       if (NULL != engine_info->setting)       free(engine_info->setting);
+       if (NULL != engine_info->name) {
+               free(engine_info->name);
+               engine_info->name = NULL;
+       }
+       if (NULL != engine_info->uuid) {
+               free(engine_info->uuid);
+               engine_info->uuid = NULL;
+       }
+       if (NULL != engine_info->setting) {
+               free(engine_info->setting);
+               engine_info->setting = NULL;
+       }
 
        tts_config_voice_s *temp_voice;
        temp_voice = g_slist_nth_data(engine_info->voices, 0);
 
        while (NULL != temp_voice) {
                if (NULL != temp_voice) {
-                       if (NULL != temp_voice->language)       free(temp_voice->language);
+                       if (NULL != temp_voice->language) {
+                               free(temp_voice->language);
+                               temp_voice->language = NULL;
+                       }
                        engine_info->voices = g_slist_remove(engine_info->voices, temp_voice);
                        free(temp_voice);
+                       temp_voice = NULL;
                }
 
                temp_voice = g_slist_nth_data(engine_info->voices, 0);
        }
 
-       if (NULL != engine_info)        free(engine_info);
+       if (NULL != engine_info) {
+               free(engine_info);
+               engine_info = NULL;
+       }
 
-       return 0;       
+       return 0;
 }
 
 int tts_parser_print_engine_info(tts_engine_info_s* engine_info)
 {
        if (NULL == engine_info) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
                return -1;
        }
 
-       SLOG(LOG_DEBUG, tts_tag(), "== get engine info ==");
-       SLOG(LOG_DEBUG, tts_tag(), " name : %s", engine_info->name);
-       SLOG(LOG_DEBUG, tts_tag(), " id   : %s", engine_info->uuid);
+       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "== get engine info ==");
+       SLOG(LOG_DEBUG, TAG_TTSCONFIG, " name : %s", engine_info->name);
+       SLOG(LOG_DEBUG, TAG_TTSCONFIG, " id   : %s", engine_info->uuid);
        if (NULL != engine_info->setting)
-               SLOG(LOG_DEBUG, tts_tag(), " setting : %s", engine_info->setting);
+               SLOG(LOG_DEBUG, TAG_TTSCONFIG, " setting : %s", engine_info->setting);
 
-       SLOG(LOG_DEBUG, tts_tag(), " voices");
+       SLOG(LOG_DEBUG, TAG_TTSCONFIG, " voices");
        GSList *iter = NULL;
        tts_config_voice_s *temp_voice;
 
@@ -249,12 +321,12 @@ int tts_parser_print_engine_info(tts_engine_info_s* engine_info)
                /* Get a first item */
                iter = g_slist_nth(engine_info->voices, 0);
 
-               int i = 1;      
+               int i = 1;
                while (NULL != iter) {
                        /*Get handle data from list*/
                        temp_voice = iter->data;
 
-                       SLOG(LOG_DEBUG, tts_tag(), "  [%dth] type(%d) lang(%s)", 
+                       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "  [%dth] type(%d) lang(%s)", 
                                i, temp_voice->type, temp_voice->language);
 
                        /*Get next item*/
@@ -262,10 +334,10 @@ int tts_parser_print_engine_info(tts_engine_info_s* engine_info)
                        i++;
                }
        } else {
-               SLOG(LOG_ERROR, tts_tag(), "  Voice is NONE");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "  Voice is NONE");
        }
 
-       SLOG(LOG_DEBUG, tts_tag(), "=====================");
+       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "@@@");
 
        return 0;
 }
@@ -273,7 +345,7 @@ int tts_parser_print_engine_info(tts_engine_info_s* engine_info)
 int tts_parser_load_config(tts_config_s** config_info)
 {
        if (NULL == config_info) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
                return -1;
        }
 
@@ -282,10 +354,14 @@ int tts_parser_load_config(tts_config_s** config_info)
        xmlChar *key;
        bool is_default_open = false;
 
+       /* For Thread safety */
+       xmlInitParser();
+
        if (0 != access(TTS_CONFIG, F_OK)) {
                doc = xmlParseFile(TTS_DEFAULT_CONFIG);
                if (doc == NULL) {
-                       SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to parse file error : %s", TTS_DEFAULT_CONFIG);
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", TTS_DEFAULT_CONFIG);
+                       xmlCleanupParser();
                        return -1;
                }
                is_default_open = true;
@@ -301,29 +377,42 @@ int tts_parser_load_config(tts_config_s** config_info)
                        usleep(10000);
 
                        if (TTS_RETRY_COUNT == retry_count) {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to parse file error : %s", TTS_CONFIG);
-                               return -1;
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", TTS_CONFIG);
+                               doc = xmlParseFile(TTS_DEFAULT_CONFIG);
+                               if (NULL == doc) {
+                                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", TTS_DEFAULT_CONFIG);
+                                       xmlCleanupParser();
+                                       return -1;
+                               }
+                               is_default_open = true;
+                               break;
                        }
                }
        }
 
        cur = xmlDocGetRootElement(doc);
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document(%p)", doc);
                xmlFreeDoc(doc);
+               doc = NULL;
+               xmlCleanupParser();
                return -1;
        }
 
        if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s. doc(%p)", TTS_TAG_CONFIG_BASE_TAG, doc);
                xmlFreeDoc(doc);
+               doc = NULL;
+               xmlCleanupParser();
                return -1;
        }
 
        cur = cur->xmlChildrenNode;
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document(%p)", doc);
                xmlFreeDoc(doc);
+               doc = NULL;
+               xmlCleanupParser();
                return -1;
        }
 
@@ -331,35 +420,40 @@ int tts_parser_load_config(tts_config_s** config_info)
        tts_config_s* temp;
        temp = (tts_config_s*)calloc(1, sizeof(tts_config_s));
        if (NULL == temp) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Out of memory");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Out of memory(%p)", doc);
                xmlFreeDoc(doc);
+               doc = NULL;
+               xmlCleanupParser();
                return -1;
        }
 
-       temp->engine_id = NULL;
-       temp->setting = NULL;
-       temp->language = NULL;
+       memset(g_engine_id, '\0', sizeof(g_engine_id));
+       memset(g_setting, '\0', sizeof(g_setting));
+       memset(g_language, '\0', sizeof(g_language));
+
+       temp->engine_id = g_engine_id;
+       temp->setting = g_setting;
+       temp->language = g_language;
 
        while (cur != NULL) {
                if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_ENGINE_ID)) {
                        key = xmlNodeGetContent(cur);
                        if (NULL != key) {
-                               if (NULL != temp->engine_id)    free(temp->engine_id);
-                               temp->engine_id = strdup((char*)key);
+                               strncpy(temp->engine_id, (char*)key, sizeof(g_engine_id) - 1);
                                xmlFree(key);
+                               key = NULL;
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] engine id is NULL");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] engine id is NULL");
                        }
                } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_ENGINE_SETTING)) {
                        key = xmlNodeGetContent(cur);
                        if (NULL != key) {
-                               if (NULL != temp->setting)      free(temp->setting);
-                               temp->setting = strdup((char*)key);
+                               strncpy(temp->setting, (char*)key, sizeof(g_setting) - 1);
                                xmlFree(key);
+                               key = NULL;
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] setting path is NULL");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] setting path is NULL");
                        }
-                       
                } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_AUTO_VOICE)) {
                        key = xmlNodeGetContent(cur);
                        if (NULL != key) {
@@ -368,13 +462,14 @@ int tts_parser_load_config(tts_config_s** config_info)
                                } else if (0 == xmlStrcmp(key, (const xmlChar *)"off")) {
                                        temp->auto_voice = false;
                                } else {
-                                       SLOG(LOG_ERROR, tts_tag(), "Auto voice is wrong");
+                                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "Auto voice is wrong");
                                        temp->auto_voice = true;
                                }
 
                                xmlFree(key);
+                               key = NULL;
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] voice type is NULL");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] voice type is NULL");
                        }
                } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_VOICE_TYPE)) {
                        key = xmlNodeGetContent(cur);
@@ -386,22 +481,23 @@ int tts_parser_load_config(tts_config_s** config_info)
                                } else if (0 == xmlStrcmp(key, (const xmlChar *)TTS_TAG_VOICE_TYPE_CHILD)) {
                                        temp->type = (int)TTS_CONFIG_VOICE_TYPE_CHILD;
                                } else {
-                                       SLOG(LOG_WARN, tts_tag(), "Voice type is user defined");
+                                       SLOG(LOG_WARN, TAG_TTSCONFIG, "Voice type is user defined");
                                        temp->type = (int)TTS_CONFIG_VOICE_TYPE_USER_DEFINED;
                                }
 
                                xmlFree(key);
+                               key = NULL;
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] voice type is NULL");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] voice type is NULL");
                        }
                } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_LANGUAGE)) {
                        key = xmlNodeGetContent(cur);
                        if (NULL != key) {
-                               if (NULL != temp->language)     free(temp->language);
-                               temp->language = strdup((char*)key);
+                               strncpy(temp->language, (char*)key, sizeof(g_language) - 1);
                                xmlFree(key);
+                               key = NULL;
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] engine uuid is NULL");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] engine uuid is NULL");
                        }
 
                } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_SPEECH_RATE)) {
@@ -410,15 +506,25 @@ int tts_parser_load_config(tts_config_s** config_info)
                                temp->speech_rate = atoi((char*)key);
                                xmlFree(key);
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] speech rate is NULL");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] speech rate is NULL");
                        }
                } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_PITCH)) {
                        key = xmlNodeGetContent(cur);
                        if (NULL != key) {
                                temp->pitch = atoi((char*)key);
                                xmlFree(key);
+                               key = NULL;
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Pitch is NULL");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Pitch is NULL");
+                       }
+               } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO)) {
+                       key = xmlNodeGetContent(cur);
+                       if (NULL != key) {
+                               temp->bg_volume_ratio = atof((char*)key);
+                               xmlFree(key);
+                               key = NULL;
+                       } else {
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Background volume ratio is NULL");
                        }
                } else {
 
@@ -431,21 +537,31 @@ int tts_parser_load_config(tts_config_s** config_info)
        g_config_doc = doc;
 
        if (true == is_default_open) {
-               int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
-               if (0 > ret) {
-                       SLOG(LOG_ERROR, tts_tag(), "[ERROR] Save result : %d", ret);
-               }
+               int retry_count = 0;
+               int ret = -1;
+               do {
+                       ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
+                       if (0 < ret)
+                               break;
+                       retry_count++;
+                       usleep(10000);
+
+                       if (TTS_RETRY_COUNT == retry_count) {
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
+                               return -1;
+                       }
+               } while (0 != ret);
 
                /* Set mode */
-               if (0 > chmod(TTS_CONFIG, 0666)) {
-                       SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to change file mode : %d", ret);
+               if (0 > chmod(TTS_CONFIG, 0600)) {
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to change file mode : %d", ret);
                }
 
                /* Set owner */
                if (0 > chown(TTS_CONFIG, 5000, 5000)) {
-                       SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to change file owner : %d", ret);
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to change file owner : %d", ret);
                }
-               SLOG(LOG_DEBUG, tts_tag(), "Default config is changed : pid(%d)", getpid());
+               SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Default config is changed : pid(%d)", getpid());
        }
 
        return 0;
@@ -453,39 +569,99 @@ int tts_parser_load_config(tts_config_s** config_info)
 
 int tts_parser_unload_config(tts_config_s* config_info)
 {
-       if (NULL != g_config_doc)       xmlFreeDoc(g_config_doc);
+       if (NULL != g_config_doc) {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Free g_config_doc(%p)", g_config_doc);
+               xmlFreeDoc(g_config_doc);
+               g_config_doc = NULL;
+       }
        if (NULL != config_info) {
-               if (NULL != config_info->engine_id)     free(config_info->engine_id);
-               if (NULL != config_info->setting)       free(config_info->setting);
-               if (NULL != config_info->language)      free(config_info->language);
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Free config_info(%p)", config_info);
                free(config_info);
+               config_info = NULL;
+       }
+
+       xmlCleanupParser();
+
+       return 0;
+}
+
+
+int tts_parser_copy_xml(const char* original, const char* destination)
+{
+       if (NULL == original || NULL == destination) {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
+               return -1;
+       }
+
+       xmlDocPtr doc = NULL;
+       if (0 == access(original, F_OK)) {
+               SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] Success to access to %s", original);
+               doc = xmlParseFile(original);
+               if (doc == NULL) {
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", original);
+                       return -1;
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", original);
+               return -1;
+       }
+
+       int ret = xmlSaveFile(destination, doc);
+       if (0 > ret) {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
+       } else {
+               static FILE* pFile;
+               pFile = fopen(destination, "r");
+               int fd = -1;
+               if (NULL == pFile) {
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", destination);
+               } else {
+                       fd = fileno(pFile);
+                       fsync(fd);
+                       fclose(pFile);
+                       SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", destination);
+               }
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", destination);
+       }
+
+       /* Set mode */
+       if (0 > chmod(destination, 0600)) {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to change file mode : %d", ret);
+       }
+
+       if (NULL != doc) {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] doc(%p)", doc);
+               xmlFreeDoc(doc);
+               doc = NULL;
        }
 
+       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[SUCCESS] Copying xml");
+
        return 0;
 }
 
 int tts_parser_set_engine(const char* engine_id, const char* setting, const char* language, int type)
 {
        if (NULL == engine_id) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
                return -1;
        }
 
        xmlNodePtr cur = NULL;
        cur = xmlDocGetRootElement(g_config_doc);
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
                return -1;
        }
 
        if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
                return -1;
        }
 
        cur = cur->xmlChildrenNode;
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
                return -1;
        }
 
@@ -510,13 +686,30 @@ int tts_parser_set_engine(const char* engine_id, const char* setting, const char
                        default:                                xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);      break;
                        }
                }
-               
+
                cur = cur->next;
        }
 
-       int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
-       if (0 > ret) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Save result : %d", ret);
+       if (0 == access(TTS_CONFIG, F_OK)) {
+               int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
+               if (0 > ret) {
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
+               } else {
+                       static FILE* pFile;
+                       pFile = fopen(TTS_CONFIG, "r");
+                       int fd = -1;
+                       if (NULL == pFile) {
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
+                       } else {
+                               fd = fileno(pFile);
+                               fsync(fd);
+                               fclose(pFile);
+                               SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
+                       }
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
        }
 
        return 0;
@@ -525,32 +718,32 @@ int tts_parser_set_engine(const char* engine_id, const char* setting, const char
 int tts_parser_set_voice(const char* language, int type)
 {
        if (NULL == language) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
                return -1;
        }
 
        xmlNodePtr cur = NULL;
        cur = xmlDocGetRootElement(g_config_doc);
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
                return -1;
        }
 
        if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
                return -1;
        }
 
        cur = cur->xmlChildrenNode;
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
                return -1;
        }
 
        while (cur != NULL) {
                if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_LANGUAGE)) {
                        xmlNodeSetContent(cur, (const xmlChar *)language);
-               } 
+               }
 
                if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_VOICE_TYPE)) {
                        switch (type) {
@@ -558,7 +751,7 @@ int tts_parser_set_voice(const char* language, int type)
                        case TTS_CONFIG_VOICE_TYPE_FEMALE:      xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);      break;
                        case TTS_CONFIG_VOICE_TYPE_CHILD:       xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_CHILD);       break;
                        default:
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Invalid type : %d", type);
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Invalid type : %d", type);
                                xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);
                                break;
                        }
@@ -567,11 +760,27 @@ int tts_parser_set_voice(const char* language, int type)
                cur = cur->next;
        }
 
-       int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
-       if (0 > ret) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Save result : %d", ret);
+       if (0 == access(TTS_CONFIG, F_OK)) {
+               int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
+               if (0 > ret) {
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
+               } else {
+                       static FILE* pFile;
+                       pFile = fopen(TTS_CONFIG, "r");
+                       int fd = -1;
+                       if (NULL == pFile) {
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
+                       } else {
+                               fd = fileno(pFile);
+                               fsync(fd);
+                               fclose(pFile);
+                               SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
+                       }
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
        }
-
        return 0;
 }
 
@@ -580,18 +789,18 @@ int tts_parser_set_auto_voice(bool value)
        xmlNodePtr cur = NULL;
        cur = xmlDocGetRootElement(g_config_doc);
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
                return -1;
        }
 
        if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
                return -1;
        }
 
        cur = cur->xmlChildrenNode;
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
                return -1;
        }
 
@@ -602,7 +811,7 @@ int tts_parser_set_auto_voice(bool value)
                        } else if (false == value) {
                                xmlNodeSetContent(cur, (const xmlChar *)"off");
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong value of auto voice");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong value of auto voice");
                                return -1;
                        }
                        break;
@@ -610,9 +819,26 @@ int tts_parser_set_auto_voice(bool value)
                cur = cur->next;
        }
 
-       int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
-       if (0 > ret) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Save result : %d", ret);
+       if (0 == access(TTS_CONFIG, F_OK)) {
+               int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
+               if (0 > ret) {
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
+               } else {
+                       static FILE* pFile;
+                       pFile = fopen(TTS_CONFIG, "r");
+                       int fd = -1;
+                       if (NULL == pFile) {
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
+                       } else {
+                               fd = fileno(pFile);
+                               fsync(fd);
+                               fclose(pFile);
+                               SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
+                       }
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
        }
 
        return 0;
@@ -623,18 +849,18 @@ int tts_parser_set_speech_rate(int value)
        xmlNodePtr cur = NULL;
        cur = xmlDocGetRootElement(g_config_doc);
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
                return -1;
        }
 
        if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
                return -1;
        }
 
        cur = cur->xmlChildrenNode;
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
                return -1;
        }
 
@@ -646,16 +872,33 @@ int tts_parser_set_speech_rate(int value)
 
                        xmlNodeSetContent(cur, (const xmlChar *)temp);
 
-                       SLOG(LOG_DEBUG, tts_tag(), "Set speech rate : %s", temp);
+                       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Set speech rate : %s", temp);
                        break;
                }
 
                cur = cur->next;
        }
 
-       int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
-       if (0 > ret) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Save result : %d", ret);
+       if (0 == access(TTS_CONFIG, F_OK)) {
+               int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
+               if (0 > ret) {
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
+               } else {
+                       static FILE* pFile;
+                       pFile = fopen(TTS_CONFIG, "r");
+                       int fd = -1;
+                       if (NULL == pFile) {
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
+                       } else {
+                               fd = fileno(pFile);
+                               fsync(fd);
+                               fclose(pFile);
+                               SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
+                       }
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
        }
 
        return 0;
@@ -666,18 +909,18 @@ int tts_parser_set_pitch(int value)
        xmlNodePtr cur = NULL;
        cur = xmlDocGetRootElement(g_config_doc);
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
                return -1;
        }
 
        if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
                return -1;
        }
 
        cur = cur->xmlChildrenNode;
        if (cur == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
                return -1;
        }
 
@@ -688,24 +931,98 @@ int tts_parser_set_pitch(int value)
                        snprintf(temp, 10, "%d", value);
                        xmlNodeSetContent(cur, (const xmlChar *)temp);
                        break;
-               } 
+               }
 
                cur = cur->next;
        }
 
-       int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
-       if (0 > ret) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Save result : %d", ret);
+       if (0 == access(TTS_CONFIG, F_OK)) {
+               int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
+               if (0 > ret) {
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
+               } else {
+                       static FILE* pFile;
+                       pFile = fopen(TTS_CONFIG, "r");
+                       int fd = -1;
+                       if (NULL == pFile) {
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
+                       } else {
+                               fd = fileno(pFile);
+                               fsync(fd);
+                               fclose(pFile);
+                               SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
+                       }
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
+       }
+
+       return 0;
+}
+
+int tts_parser_set_bg_volume_ratio(double value)
+{
+       xmlNodePtr cur = NULL;
+       cur = xmlDocGetRootElement(g_config_doc);
+       if (cur == NULL) {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
+               return -1;
+       }
+
+       if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
+               return -1;
+       }
+
+       cur = cur->xmlChildrenNode;
+       if (cur == NULL) {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
+               return -1;
+       }
+
+       while (cur != NULL) {
+               if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO)) {
+                       char temp[10];
+                       memset(temp, '\0', 10);
+                       snprintf(temp, 10, "%lf", value);
+                       xmlNodeSetContent(cur, (const xmlChar *)temp);
+                       break;
+               }
+
+               cur = cur->next;
+       }
+
+       if (0 == access(TTS_CONFIG, F_OK)) {
+               int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
+               if (0 > ret) {
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
+               } else {
+                       static FILE* pFile;
+                       pFile = fopen(TTS_CONFIG, "r");
+                       int fd = -1;
+                       if (NULL == pFile) {
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
+                       } else {
+                               fd = fileno(pFile);
+                               fsync(fd);
+                               fclose(pFile);
+                               SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
+                       }
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
        }
 
        return 0;
 }
 
 int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voice, char** language, int* voice_type, 
-                                  int* speech_rate, int* pitch)
+                                  int* speech_rate, int* pitch, double* bg_volume_ratio)
 {
        if (NULL == engine || NULL == setting || NULL == language || NULL == voice_type || NULL == speech_rate) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
                return -1;
        }
 
@@ -718,15 +1035,18 @@ int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voic
 
        int retry_count = 0;
        while (NULL == doc) {
-               doc = xmlParseFile(TTS_CONFIG);
-               if (NULL != doc) {
-                       break;
+               if (0 == access(TTS_CONFIG, F_OK)) {
+                       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] Success to access to %s", TTS_CONFIG);
+                       doc = xmlParseFile(TTS_CONFIG);
+                       if (NULL != doc) {
+                               break;
+                       }
                }
                retry_count++;
                usleep(10000);
 
                if (TTS_RETRY_COUNT == retry_count) {
-                       SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to parse file error : %s", TTS_CONFIG);
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", TTS_CONFIG);
                        return -1;
                }
        }
@@ -734,23 +1054,26 @@ int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voic
        cur_new = xmlDocGetRootElement(doc);
        cur_old = xmlDocGetRootElement(g_config_doc);
        if (cur_new == NULL || cur_old == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document(%p)", doc);
                xmlFreeDoc(doc);
+               doc = NULL;
                return -1;
        }
 
        if (xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_BASE_TAG) || 
        xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_BASE_TAG)) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s. doc(%p)", TTS_TAG_CONFIG_BASE_TAG, doc);
                xmlFreeDoc(doc);
+               doc = NULL;
                return -1;
        }
 
        cur_new = cur_new->xmlChildrenNode;
        cur_old = cur_old->xmlChildrenNode;
        if (cur_new == NULL || cur_old == NULL) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document(%p)", doc);
                xmlFreeDoc(doc);
+               doc = NULL;
                return -1;
        }
 
@@ -762,17 +1085,22 @@ int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voic
                                        key_new = xmlNodeGetContent(cur_new);
                                        if (NULL != key_new) {
                                                if (0 != xmlStrcmp(key_old, key_new)) {
-                                                       SLOG(LOG_DEBUG, tts_tag(), "Old engine id(%s), New engine(%s)", 
+                                                       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old engine id(%s), New engine(%s)", 
                                                                (char*)key_old, (char*)key_new);
-                                                       if (NULL != *engine)    free(*engine);
+                                                       if (NULL != *engine) {
+                                                               free(*engine);
+                                                               *engine = NULL;
+                                                       }
                                                        *engine = strdup((char*)key_new);
                                                }
                                                xmlFree(key_new);
+                                               key_new = NULL;
                                        }
                                        xmlFree(key_old);
+                                       key_old = NULL;
                                }
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
                        }
                } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_SETTING)) {
                        if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_SETTING)) {
@@ -781,17 +1109,22 @@ int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voic
                                        key_new = xmlNodeGetContent(cur_new);
                                        if (NULL != key_new) {
                                                if (0 != xmlStrcmp(key_old, key_new)) {
-                                                       SLOG(LOG_DEBUG, tts_tag(), "Old engine setting(%s), New engine setting(%s)", 
+                                                       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old engine setting(%s), New engine setting(%s)", 
                                                                (char*)key_old, (char*)key_new);
-                                                       if (NULL != *setting)   free(*setting);
+                                                       if (NULL != *setting) {
+                                                               free(*setting);
+                                                               *setting = NULL;
+                                                       }
                                                        *setting = strdup((char*)key_new);
                                                }
                                                xmlFree(key_new);
+                                               key_new = NULL;
                                        }
                                        xmlFree(key_old);
+                                       key_old = NULL;
                                }
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
                        }
                } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_AUTO_VOICE)) {
                        if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_AUTO_VOICE)) {
@@ -800,7 +1133,7 @@ int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voic
                                        key_new = xmlNodeGetContent(cur_new);
                                        if (NULL != key_new) {
                                                if (0 != xmlStrcmp(key_old, key_new)) {
-                                                       SLOG(LOG_DEBUG, tts_tag(), "Old auto voice (%s), New auto voice(%s)", 
+                                                       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old auto voice (%s), New auto voice(%s)", 
                                                                (char*)key_old, (char*)key_new);
                                                        if (0 == xmlStrcmp((const xmlChar*)"on", key_new)) {
                                                                *auto_voice = true;
@@ -809,11 +1142,13 @@ int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voic
                                                        }
                                                }
                                                xmlFree(key_new);
+                                               key_new = NULL;
                                        }
                                        xmlFree(key_old);
+                                       key_old = NULL;
                                }
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
                        }
                } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_LANGUAGE)) {
                        if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_LANGUAGE)) {
@@ -822,17 +1157,22 @@ int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voic
                                        key_new = xmlNodeGetContent(cur_new);
                                        if (NULL != key_new) {
                                                if (0 != xmlStrcmp(key_old, key_new)) {
-                                                       SLOG(LOG_DEBUG, tts_tag(), "Old language(%s), New language(%s)", 
+                                                       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old language(%s), New language(%s)", 
                                                                (char*)key_old, (char*)key_new);
-                                                       if (NULL != *language)  free(*language);
+                                                       if (NULL != *language) {
+                                                               free(*language);
+                                                               *language = NULL;
+                                                       }
                                                        *language = strdup((char*)key_new);
                                                }
                                                xmlFree(key_new);
+                                               key_new = NULL;
                                        }
                                        xmlFree(key_old);
+                                       key_old = NULL;
                                }
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
                        }
                } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_VOICE_TYPE)) {
                        if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_VOICE_TYPE)) {
@@ -841,7 +1181,7 @@ int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voic
                                        key_new = xmlNodeGetContent(cur_new);
                                        if (NULL != key_new) {
                                                if (0 != xmlStrcmp(key_old, key_new)) {
-                                                       SLOG(LOG_DEBUG, tts_tag(), "Old voice type(%s), New voice type(%s)", 
+                                                       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old voice type(%s), New voice type(%s)", 
                                                                (char*)key_old, (char*)key_new);
                                                        if (0 == xmlStrcmp(key_new, (const xmlChar *)TTS_TAG_VOICE_TYPE_FEMALE)) {
                                                                *voice_type = (int)TTS_CONFIG_VOICE_TYPE_FEMALE;
@@ -850,15 +1190,17 @@ int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voic
                                                        } else if (0 == xmlStrcmp(key_new, (const xmlChar *)TTS_TAG_VOICE_TYPE_CHILD)) {
                                                                *voice_type = (int)TTS_CONFIG_VOICE_TYPE_CHILD;
                                                        } else {
-                                                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] New voice type is not valid");
+                                                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] New voice type is not valid");
                                                        }
                                                }
                                                xmlFree(key_new);
+                                               key_new = NULL;
                                        }
                                        xmlFree(key_old);
+                                       key_old = NULL;
                                }
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
                        }
                } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_SPEECH_RATE)) {
                        if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_SPEECH_RATE)) {
@@ -867,16 +1209,18 @@ int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voic
                                        key_new = xmlNodeGetContent(cur_new);
                                        if (NULL != key_new) {
                                                if (0 != xmlStrcmp(key_old, key_new)) {
-                                                       SLOG(LOG_DEBUG, tts_tag(), "Old speech rate(%s), New speech rate(%s)", 
+                                                       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old speech rate(%s), New speech rate(%s)", 
                                                                (char*)key_old, (char*)key_new);
                                                        *speech_rate = atoi((char*)key_new);
                                                }
                                                xmlFree(key_new);
+                                               key_new = NULL;
                                        }
                                        xmlFree(key_old);
+                                       key_old = NULL;
                                }
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
                        }
                } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_PITCH)) {
                        if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_PITCH)) {
@@ -885,16 +1229,38 @@ int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voic
                                        key_new = xmlNodeGetContent(cur_new);
                                        if (NULL != key_new) {
                                                if (0 != xmlStrcmp(key_old, key_new)) {
-                                                       SLOG(LOG_DEBUG, tts_tag(), "Old pitch(%s), New pitch(%s)", 
+                                                       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old pitch(%s), New pitch(%s)", 
                                                                (char*)key_old, (char*)key_new);
                                                        *pitch = atoi((char*)key_new);
                                                }
                                                xmlFree(key_new);
+                                               key_new = NULL;
+                                       }
+                                       xmlFree(key_old);
+                                       key_old = NULL;
+                               }
+                       } else {
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
+                       }
+               } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO)) {
+                       if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO)) {
+                               key_old = xmlNodeGetContent(cur_old);
+                               if (NULL != key_old) {
+                                       key_new = xmlNodeGetContent(cur_new);
+                                       if (NULL != key_new) {
+                                               if (0 != xmlStrcmp(key_old, key_new)) {
+                                                       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old bg volume ratio(%s), New bg volume ratio(%s)", 
+                                                               (char*)key_old, (char*)key_new);
+                                                       *bg_volume_ratio = atof((char*)key_new);
+                                               }
+                                               xmlFree(key_new);
+                                               key_new = NULL;
                                        }
                                        xmlFree(key_old);
+                                       key_old = NULL;
                                }
                        } else {
-                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
                        }
                } else {
 
@@ -903,9 +1269,54 @@ int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voic
                cur_new = cur_new->next;
                cur_old = cur_old->next;
        }
-       
-       xmlFreeDoc(g_config_doc);
+
+       if (NULL != g_config_doc) {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Free g_config_doc(%p)", g_config_doc);
+               xmlFreeDoc(g_config_doc);
+               g_config_doc = NULL;
+       }
        g_config_doc = doc;
 
        return 0;
-}
\ No newline at end of file
+}
+
+int tts_parser_reset()
+{
+       SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] Reset g_config_doc as %s", TTS_DEFAULT_CONFIG);
+
+       if (NULL != g_config_doc) {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Free g_config_doc(%p)", g_config_doc);
+               xmlFreeDoc(g_config_doc);
+               g_config_doc = NULL;
+       }
+
+       g_config_doc = xmlParseFile(TTS_DEFAULT_CONFIG);
+       if (NULL == g_config_doc) {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse %s", TTS_DEFAULT_CONFIG);
+               return -1;
+       }
+
+       if (0 == access(TTS_CONFIG, F_OK)) {
+               int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
+               if (0 > ret) {
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to save %s", TTS_CONFIG);
+               } else {
+                       static FILE* pFile;
+                       pFile = fopen(TTS_CONFIG, "r");
+                       int fd = -1;
+                       if (NULL == pFile) {
+                               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
+                       } else {
+                               fd = fileno(pFile);
+                               fsync(fd);
+                               fclose(pFile);
+                               SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
+                       }
+                       SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
+       }
+
+       return 0;
+}