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