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