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