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