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