Add multi-user support
[platform/core/uifw/tts.git] / server / ttsd_config_noti.c
1 /*
2 *  Copyright (c) 2012, 2013 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 <Ecore.h>
15 #include <Ecore_File.h>
16 #include <runtime_info.h>
17 #include <sys/inotify.h>
18 #include <vconf.h>
19
20 /* For multi-user support */
21 #include <tzplatform_config.h>
22
23 #include "ttsd_main.h"
24 #include "ttsd_config.h"
25 #include "ttsd_engine_agent.h"
26 #include "ttsd_data.h"
27
28 #define NOTI_ERROR_FILE_NAME            tzplatform_mkpath(TZ_USER_HOME, ".voice/ttsd_noti.err")
29
30 #define ENGINE_ID       "ENGINE_ID"
31 #define VOICE           "VOICE"
32 #define SPEED           "SPEED"
33
34
35 static char*    g_engine_id;
36 static char*    g_language;
37 static int      g_vc_type;
38 static int      g_speed;
39
40 static Ecore_Fd_Handler* g_fd_handler_noti = NULL;
41 static int g_fd_noti;
42 static int g_wd_noti;
43
44 static ttsd_config_changed_cb g_callback;
45
46
47 int __ttsd_config_compare()
48 {
49         FILE* config_fp;
50         char buf_id[256] = {0};
51         char buf_param[256] = {0};
52         int int_param = 0;
53
54         config_fp = fopen(DEFAULT_CONFIG_FILE_NAME, "r");
55
56         if (NULL == config_fp) {
57                 SLOG(LOG_ERROR, get_tag(), "[Config ERROR] Not open file(%s)", DEFAULT_CONFIG_FILE_NAME);
58
59                 return -1;
60         }
61
62         /* Read engine id */
63         if (EOF == fscanf(config_fp, "%s %s", buf_id, buf_param)) {
64                 fclose(config_fp);
65                 SLOG(LOG_ERROR, get_tag(), "[Config WARNING] Fail to read config (engine id)");
66                 return -1;
67         } else {
68                 if (0 == strncmp(ENGINE_ID, buf_id, strlen(ENGINE_ID))) {
69                         if (NULL != g_engine_id) {
70                                 if (0 != strcmp(g_engine_id, buf_param)) {
71                                         free(g_engine_id);
72                                         g_engine_id = strdup(buf_param);
73
74                                         SLOG(LOG_DEBUG, get_tag(), "[Config] engine id is changed : %s", g_engine_id);
75
76                                         if (NULL != g_callback)
77                                                 g_callback(TTS_CONFIG_TYPE_ENGINE, g_engine_id, 0);
78                                 }
79                         } else {
80                                 SLOG(LOG_ERROR, get_tag(), "[Config ERROR] Current engine id is not available");
81                                 g_engine_id = strdup(buf_param);
82                                 if (NULL != g_callback)
83                                         g_callback(TTS_CONFIG_TYPE_ENGINE, g_engine_id, 0);
84                         }
85                 } else {
86                         fclose(config_fp);
87                         SLOG(LOG_ERROR, get_tag(), "[Config] Fail to load config (engine id)");
88                         return -1;
89                 }
90         }
91
92         /* Read voice */
93         if (EOF == fscanf(config_fp, "%s %s %d", buf_id, buf_param, &int_param)) {
94                 fclose(config_fp);
95                 SLOG(LOG_WARN, get_tag(), "[Config WARNING] Fail to read config (voice)");
96                 return -1;
97         } else {
98                 if (0 == strncmp(VOICE, buf_id, strlen(VOICE))) {
99                         if (NULL != g_language) {
100                                 if ((0 != strcmp(g_language, buf_param)) || (g_vc_type != int_param)) {
101                                         free(g_language);
102                                         g_language = strdup(buf_param);
103                                         g_vc_type = int_param;
104
105                                         SLOG(LOG_DEBUG, get_tag(), "[Config] voice is changed : lang(%s) type(%d)", g_language, g_vc_type);
106
107                                         if (NULL != g_callback)
108                                                 g_callback(TTS_CONFIG_TYPE_VOICE, g_language, g_vc_type);
109                                 }
110                         } else {
111                                 SLOG(LOG_ERROR, get_tag(), "[Config ERROR] Current voice is not available");
112                                 g_language = strdup(buf_param);
113                                 g_vc_type = int_param;
114
115                                 if (NULL != g_callback)
116                                         g_callback(TTS_CONFIG_TYPE_VOICE, g_language, g_vc_type);
117                         }
118                 } else {
119                         fclose(config_fp);
120                         SLOG(LOG_WARN, get_tag(), "[Config WARNING] Fail to load config (voice)");
121                         return -1;
122                 }
123         }
124
125         /* Read speed */
126         if (EOF == fscanf(config_fp, "%s %d", buf_id, &int_param)) {
127                 fclose(config_fp);
128                 SLOG(LOG_WARN, get_tag(), "[Config WARNING] Fail to read config (speed)");
129                 return -1;
130         } else {
131                 if (0 == strncmp(SPEED, buf_id, strlen(SPEED))) {
132                         if (g_speed != int_param) {
133                                 g_speed = int_param;
134
135                                 SLOG(LOG_DEBUG, get_tag(), "[Config] speech rate is changed : %d", g_speed);
136
137                                 if (NULL != g_callback)
138                                         g_callback(TTS_CONFIG_TYPE_SPEED, NULL, g_speed);
139                         }
140                 } else {
141                         fclose(config_fp);
142                         SLOG(LOG_WARN, get_tag(), "[Config WARNING] Fail to load config (speed)");
143                         return -1;
144                 }
145         }
146
147         fclose(config_fp);
148
149         return 0;
150 }
151
152 int __ttsd_config_save()
153 {
154         if (0 != access(DEFAULT_CONFIG_FILE_NAME, R_OK|W_OK)) {
155                 if (0 == ecore_file_mkpath(CONFIG_DIRECTORY)) {
156                         SLOG(LOG_WARN, get_tag(), "[Config WARNING] Fail to create directory (%s)", CONFIG_DIRECTORY);
157                 } else {
158                         SLOG(LOG_DEBUG, get_tag(), "[Config] Create directory (%s)", CONFIG_DIRECTORY);
159                 }
160         }
161
162         FILE* config_fp;
163         config_fp = fopen(DEFAULT_CONFIG_FILE_NAME, "w+");
164
165         if (NULL == config_fp) {
166                 /* make file and file default */
167                 SLOG(LOG_WARN, get_tag(), "[Config WARNING] Fail to open config (%s)", DEFAULT_CONFIG_FILE_NAME);
168                 return -1;
169         }
170
171         SLOG(LOG_DEBUG, get_tag(), "[Config] Rewrite config file");
172
173         /* Write engine id */
174         fprintf(config_fp, "%s %s\n", ENGINE_ID, g_engine_id);
175
176         /* Write voice */
177         fprintf(config_fp, "%s %s %d\n", VOICE, g_language, g_vc_type);
178
179         /* Read speed */
180         fprintf(config_fp, "%s %d\n", SPEED, g_speed);
181
182         fclose(config_fp);
183
184         return 0;
185 }
186
187 int __ttsd_config_load()
188 {
189         FILE* config_fp;
190         char buf_id[256] = {0};
191         char buf_param[256] = {0};
192         int int_param = 0;
193         bool is_default_open = false;
194
195         config_fp = fopen(DEFAULT_CONFIG_FILE_NAME, "r");
196
197         if (NULL == config_fp) {
198                 SLOG(LOG_WARN, get_tag(), "[Config WARNING] Not open file(%s)", DEFAULT_CONFIG_FILE_NAME);
199
200                 config_fp = fopen(CONFIG_DEFAULT, "r");
201                 if (NULL == config_fp) {
202                         SLOG(LOG_ERROR, get_tag(), "[Config WARNING] Not open original config file(%s)", CONFIG_DEFAULT);
203                         return -1;
204                 }
205
206                 is_default_open = true;
207         }
208
209         /* Read engine id */
210         if (EOF == fscanf(config_fp, "%s %s", buf_id, buf_param)) {
211                 fclose(config_fp);
212                 SLOG(LOG_WARN, get_tag(), "[Config WARNING] Fail to read config (engine id)");
213                 return -1;
214         } else {
215                 if (0 == strncmp(ENGINE_ID, buf_id, strlen(ENGINE_ID))) {
216                         g_engine_id = strdup(buf_param);
217                 } else {
218                         fclose(config_fp);
219                         SLOG(LOG_WARN, get_tag(), "[Config WARNING] Fail to load config (engine id)");
220                         return -1;
221                 }
222         }
223
224         /* Read voice */
225         if (EOF == fscanf(config_fp, "%s %s %d", buf_id, buf_param, &int_param)) {
226                 fclose(config_fp);
227                 SLOG(LOG_WARN, get_tag(), "[Config WARNING] Fail to read config (voice)");
228                 __ttsd_config_save();
229                 return -1;
230         } else {
231                 if (0 == strncmp(VOICE, buf_id, strlen(VOICE))) {
232                         g_language = strdup(buf_param);
233                         g_vc_type = int_param;
234                 } else {
235                         fclose(config_fp);
236                         SLOG(LOG_WARN, get_tag(), "[Config WARNING] Fail to load config (voice)");
237                         return -1;
238                 }
239         }
240
241         if (true == is_default_open) {
242                 /* Change default language to display language */
243                 char* value;
244                 value = vconf_get_str(VCONFKEY_LANGSET);
245
246                 if (NULL != value) {
247                         SLOG(LOG_DEBUG, get_tag(), "[Config] System language : %s", value);
248                         strncpy(g_language, value, strlen(g_language));
249                         SLOG(LOG_DEBUG, get_tag(), "[Config] Default language : %s", g_language);
250
251                         free(value);
252                 } else {
253                         SLOG(LOG_ERROR, get_tag(), "[Config ERROR] Fail to get system language");
254                 }
255         }
256
257         /* Read speed */
258         if (EOF == fscanf(config_fp, "%s %d", buf_id, &int_param)) {
259                 fclose(config_fp);
260                 SLOG(LOG_WARN, get_tag(), "[Config WARNING] Fail to read config (speed)");
261                 return -1;
262         } else {
263                 if (0 == strncmp(SPEED, buf_id, strlen(SPEED))) {
264                         g_speed = int_param;
265                 } else {
266                         fclose(config_fp);
267                         SLOG(LOG_WARN, get_tag(), "[Config WARNING] Fail to load config (speed)");
268                         return -1;
269                 }
270         }
271
272         fclose(config_fp);
273
274         SLOG(LOG_DEBUG, get_tag(), "[Config] Load config : engine(%s), voice(%s,%d), speed(%d)",
275                 g_engine_id, g_language, g_vc_type, g_speed);
276
277         if (true == is_default_open) {
278                 if(0 == __ttsd_config_save()) {
279                         SLOG(LOG_DEBUG, get_tag(), "[Config] Create config(%s)", DEFAULT_CONFIG_FILE_NAME);
280                 }
281         }
282
283         return 0;
284 }
285
286 static Eina_Bool inotify_event_callback(void* data, Ecore_Fd_Handler *fd_handler)
287 {
288         SLOG(LOG_DEBUG, get_tag(), "===== [Config] Inotify event call");
289
290         int length;
291         char buffer[sizeof(struct inotify_event)];
292         memset(buffer, 0, (sizeof(struct inotify_event)));
293
294         length = read(g_fd_noti, buffer, (sizeof(struct inotify_event)));
295         if (0 > length) {
296                 SLOG(LOG_ERROR, get_tag(), "[Config] Empty Inotify event");
297                 SLOG(LOG_DEBUG, get_tag(), "=====");
298                 SLOG(LOG_DEBUG, get_tag(), " ");
299                 return ECORE_CALLBACK_RENEW; 
300         }
301
302         struct inotify_event *event;
303         event = (struct inotify_event *)&buffer;
304
305         if (IN_CLOSE_WRITE == event->mask) {
306                 __ttsd_config_compare();
307         } else {
308                 SLOG(LOG_ERROR, get_tag(), "[Config] Undefined event");
309         }
310
311         SLOG(LOG_DEBUG, get_tag(), "=====");
312         SLOG(LOG_DEBUG, get_tag(), " ");
313
314         return ECORE_CALLBACK_PASS_ON;
315 }
316
317 int __config_file_open_connection()
318 {
319         /* get file notification handler */
320         int fd;
321         int wd;
322
323         fd = inotify_init();
324         if (fd < 0) {
325                 SLOG(LOG_ERROR, get_tag(), "[Config ERROR] Fail get inotify_fd");
326                 return -1;
327         }
328         g_fd_noti = fd;
329
330         wd = inotify_add_watch(fd, DEFAULT_CONFIG_FILE_NAME, IN_CLOSE_WRITE);
331         g_wd_noti = wd;
332         g_fd_handler_noti = ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)inotify_event_callback, NULL, NULL, NULL);                
333         if (NULL == g_fd_handler_noti) {
334                 SLOG(LOG_ERROR, get_tag(), "[Config ERROR] Fail to get handler_noti");
335                 return -1;
336         }
337
338         return 0;
339 }
340
341 int ttsd_config_initialize(ttsd_config_changed_cb callback)
342 {
343         g_engine_id = NULL;
344         g_language = NULL;
345         g_vc_type = 1;
346         g_speed = 3;
347
348         g_callback = callback;
349
350         ecore_file_mkpath(CONFIG_DIRECTORY);
351
352         __ttsd_config_load();
353
354         if (0 != __config_file_open_connection()) {
355                 return -1;
356         }
357
358         return 0;
359 }
360
361 int ttsd_config_finalize()
362 {
363         if (NULL != g_language) {
364                 free(g_language);
365         }
366
367         if (NULL != g_engine_id) {
368                 free(g_engine_id);
369         }
370
371         /* del inotify variable */
372         ecore_main_fd_handler_del(g_fd_handler_noti);
373         inotify_rm_watch(g_fd_noti, g_wd_noti);
374         close(g_fd_noti);
375
376         return 0;
377 }
378
379 int ttsd_config_update_language()
380 {
381         /* no work in notification mode */
382         return 0;
383 }
384
385 int ttsd_config_get_default_engine(char** engine_id)
386 {
387         if (NULL == engine_id)
388                 return -1;
389
390         if (NULL != g_engine_id) {
391                 *engine_id = strdup(g_engine_id);
392         } else {
393                 SLOG(LOG_ERROR, get_tag(), "[Config ERROR] Current engine id is NULL");
394                 return -1;
395         }
396
397         return 0;
398 }
399
400 int ttsd_config_set_default_engine(const char* engine_id)
401 {
402         /* Not available in notification mode */
403         return 0;
404 }
405
406 int ttsd_config_get_default_voice(char** language, int* type)
407 {
408         if (NULL == language || NULL == type)
409                 return -1;
410
411         if (NULL != g_language) {
412                 *language = strdup(g_language);
413                 *type = g_vc_type;
414         } else {
415                 SLOG(LOG_ERROR, get_tag(), "[Config ERROR] Current language is NULL");
416                 return -1;
417         }
418         
419         return 0;
420 }
421
422 int ttsd_config_set_default_voice(const char* language, int type)
423 {
424         /* Not available in notification mode */
425         return 0;
426 }
427
428 int ttsd_config_get_default_speed(int* speed)
429 {
430         if (NULL == speed)
431                 return -1;
432
433         *speed = g_speed;
434
435         return 0;
436 }
437
438 int ttsd_config_set_default_speed(int speed)
439 {
440         /* Not available in notification mode */
441         return 0;
442 }
443
444 int ttsd_config_save_error(int uid, int uttid, const char* lang, int vctype, const char* text, 
445                            const char* func, int line, const char* message)
446 {
447         SLOG(LOG_ERROR, get_tag(), "=============== TTS ERROR LOG ====================");
448
449         SLOG(LOG_ERROR, get_tag(), "uid(%d) uttid(%d)", uid, uttid);
450
451         if (NULL != func)       SLOG(LOG_ERROR, get_tag(), "Function(%s) Line(%d)", func, line);
452         if (NULL != message)    SLOG(LOG_ERROR, get_tag(), "Message(%s)", message);
453         if (NULL != lang)       SLOG(LOG_ERROR, get_tag(), "Lang(%s), type(%d)", lang, vctype);
454         if (NULL != text)       SLOG(LOG_ERROR, get_tag(), "Text(%s)", text);
455
456         SLOG(LOG_ERROR, get_tag(), "==================================================");
457
458         return 0;
459 }