Fix to remove timer when daemon is destroyed
[platform/core/uifw/tts.git] / client / tts_setting.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
15 #include <sys/wait.h>
16 #include <Ecore.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <dirent.h>
20
21 #include "tts_main.h"
22 #include "tts_setting.h"
23 #include "tts_setting_dbus.h"
24
25 static bool g_is_daemon_started = false;
26
27 static Ecore_Timer* g_setting_connect_timer = NULL;
28
29 static int __check_setting_tts_daemon();
30
31 static tts_setting_state_e g_state = TTS_SETTING_STATE_NONE;
32
33 static tts_setting_initialized_cb g_initialized_cb;
34 static void* g_user_data;
35
36 static int g_reason;
37
38 /* API Implementation */
39 static Eina_Bool __tts_setting_initialized(void *data)
40 {
41         g_initialized_cb(g_state, g_reason, g_user_data);
42
43         return EINA_FALSE;
44 }
45
46 static Eina_Bool __tts_setting_connect_daemon(void *data)
47 {
48         /* Send hello */
49         if (0 != tts_setting_dbus_request_hello()) {
50                 if (false == g_is_daemon_started) {
51                         g_is_daemon_started = true;
52                         __check_setting_tts_daemon();
53                 }
54                 return EINA_TRUE;
55         }
56
57         SLOG(LOG_DEBUG, TAG_TTSC, "===== Connect daemon");
58
59         /* do request initialize */
60         int ret = -1;
61
62         ret = tts_setting_dbus_request_initialize();
63
64         if (TTS_SETTING_ERROR_ENGINE_NOT_FOUND == ret) {
65                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Engine not found");
66         } else if (TTS_SETTING_ERROR_NONE != ret) {
67                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to connection : %d", ret);
68         } else {
69                 /* success to connect tts-daemon */
70                 g_state = TTS_SETTING_STATE_READY;
71         }
72
73         g_reason = ret;
74
75         ecore_timer_add(0, __tts_setting_initialized, NULL);
76
77         g_setting_connect_timer = NULL;
78
79         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
80         SLOG(LOG_DEBUG, TAG_TTSC, " ");
81
82         return EINA_FALSE;
83 }
84
85 int tts_setting_initialize(tts_setting_initialized_cb callback, void* user_data)
86 {
87         SLOG(LOG_DEBUG, TAG_TTSC, "===== Initialize TTS Setting");
88
89         if (TTS_SETTING_STATE_READY == g_state) {
90                 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] TTS Setting has already been initialized.");
91                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
92                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
93                 return TTS_SETTING_ERROR_NONE;
94         }
95
96         if( 0 != tts_setting_dbus_open_connection() ) {
97                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to open connection");
98                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
99                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
100                 return TTS_SETTING_ERROR_OPERATION_FAILED;
101         }
102
103         g_initialized_cb = callback;
104         g_user_data = user_data;
105
106         g_setting_connect_timer = ecore_timer_add(0, __tts_setting_connect_daemon, NULL);
107
108         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
109         SLOG(LOG_DEBUG, TAG_TTSC, " ");
110
111         return TTS_SETTING_ERROR_NONE;
112 }
113
114 int tts_setting_finalize()
115 {
116         SLOG(LOG_DEBUG, TAG_TTSC, "===== Finalize TTS Setting");
117
118         int ret = 0;
119
120         if (TTS_SETTING_STATE_READY == g_state) {
121                 ret = tts_setting_dbus_request_finalilze(); 
122                 if (0 != ret) {
123                         SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret);
124                 }
125         }
126
127         if (NULL != g_setting_connect_timer) {
128                 SLOG(LOG_DEBUG, TAG_TTSC, "Setting Connect Timer is remained");
129                 ecore_timer_del(g_setting_connect_timer);
130         }
131
132         g_is_daemon_started = false;
133         
134         if (0 != tts_setting_dbus_close_connection()) {
135                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to close connection");
136         } else {
137                 SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Finalize");
138         }
139
140         g_state = TTS_SETTING_STATE_NONE;
141         
142         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
143         SLOG(LOG_DEBUG, TAG_TTSC, " ");
144
145         return TTS_SETTING_ERROR_NONE;
146 }
147
148 int tts_setting_foreach_supported_engines(tts_setting_supported_engine_cb callback, void* user_data)
149 {    
150         SLOG(LOG_DEBUG, TAG_TTSC, "===== Foreach supported engines");
151
152         if (TTS_SETTING_STATE_NONE == g_state) {
153                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized");
154                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
155                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
156                 return TTS_SETTING_ERROR_INVALID_STATE;
157         }
158
159         if (NULL == callback) {
160                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Callback is NULL");
161                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
162                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
163                 return TTS_SETTING_ERROR_INVALID_PARAMETER;
164         }
165
166         int ret = tts_setting_dbus_request_get_engine_list(callback, user_data);
167         if (0 != ret) {
168                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret);
169         } else {
170                 SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Foreach supported engines");
171         }
172         
173         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
174         SLOG(LOG_DEBUG, TAG_TTSC, " ");
175                 
176         return ret;
177 }
178
179 int tts_setting_get_engine(char** engine_id)
180 {
181         SLOG(LOG_DEBUG, TAG_TTSC, "===== Get current engine");
182
183         if (TTS_SETTING_STATE_NONE == g_state) {
184                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized");
185                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
186                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
187                 return TTS_SETTING_ERROR_INVALID_STATE;
188         }
189
190         if (NULL == engine_id) {
191                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Engine id is NULL");
192                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
193                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
194                 return TTS_SETTING_ERROR_INVALID_PARAMETER;
195         }
196
197         int ret = tts_setting_dbus_request_get_engine(engine_id);
198         if (0 != ret) {
199                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret);
200         } else {
201                 SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Get current engine");
202         }
203
204         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
205         SLOG(LOG_DEBUG, TAG_TTSC, " ");
206
207         return ret;
208 }
209
210 int tts_setting_set_engine(const char* engine_id)
211 {
212         SLOG(LOG_DEBUG, TAG_TTSC, "===== Set current engine");
213
214         if (TTS_SETTING_STATE_NONE == g_state) {
215                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized");
216                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
217                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
218                 return TTS_SETTING_ERROR_INVALID_STATE;
219         }
220
221         if (NULL == engine_id) {
222                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Engine id is NULL");
223                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
224                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
225                 return TTS_SETTING_ERROR_INVALID_PARAMETER;
226         }
227
228         int ret = tts_setting_dbus_request_set_engine(engine_id);
229         if (0 != ret) {
230                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret);
231         } else {
232                 SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set current engine");
233         }
234         
235         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
236         SLOG(LOG_DEBUG, TAG_TTSC, " ");
237     
238         return ret;
239 }
240
241 int tts_setting_foreach_surpported_voices(tts_setting_supported_voice_cb callback, void* user_data)
242 {
243         SLOG(LOG_DEBUG, TAG_TTSC, "===== Foreach supported voices");
244
245         if (TTS_SETTING_STATE_NONE == g_state) {
246                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized");
247                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
248                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
249                 return TTS_SETTING_ERROR_INVALID_STATE;
250         }
251
252         if (NULL == callback) {
253                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Param is NULL");
254                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
255                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
256                 return TTS_SETTING_ERROR_INVALID_PARAMETER;
257         }
258
259         int ret = tts_setting_dbus_request_get_voice_list(callback, user_data);
260
261         if (0 != ret) {
262                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret);
263         } else {
264                 SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Foreach supported voices");
265         }
266
267         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
268         SLOG(LOG_DEBUG, TAG_TTSC, " ");
269
270         return ret;
271 }
272
273 int tts_setting_get_default_voice(char** language, tts_setting_voice_type_e* voice_type)
274 {
275         SLOG(LOG_DEBUG, TAG_TTSC, "===== Get default voice");
276
277         if (TTS_SETTING_STATE_NONE == g_state) {
278                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized");
279                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
280                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
281                 return TTS_SETTING_ERROR_INVALID_STATE;
282         }
283
284         if (NULL == language || NULL == voice_type) {
285                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is NULL");
286                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
287                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
288                 return TTS_SETTING_ERROR_INVALID_PARAMETER;
289         }
290
291         int ret = tts_setting_dbus_request_get_default_voice(language, voice_type);
292         if (0 != ret) {
293                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret);
294         } else {
295                 SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Foreach supported voices");
296         }
297
298         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
299         SLOG(LOG_DEBUG, TAG_TTSC, " ");
300
301         return ret;
302 }
303
304 int tts_setting_set_default_voice(const char* language, tts_setting_voice_type_e voice_type)
305 {
306         SLOG(LOG_DEBUG, TAG_TTSC, "===== Set default voice");
307
308         if (TTS_SETTING_STATE_NONE == g_state) {
309                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized");
310                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
311                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
312                 return TTS_SETTING_ERROR_INVALID_STATE;
313         }
314
315         if (NULL == language) {
316                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is NULL");
317                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
318                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
319                 return TTS_SETTING_ERROR_INVALID_PARAMETER;
320         }
321
322         if (voice_type < TTS_SETTING_VOICE_TYPE_MALE || TTS_SETTING_VOICE_TYPE_USER3 < voice_type ) {
323                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Invalid voice type");
324                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
325                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
326                 return TTS_SETTING_ERROR_INVALID_PARAMETER;
327         }
328
329         int ret = tts_setting_dbus_request_set_default_voice(language, voice_type);
330         if (0 != ret) {
331                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret);
332         } else {
333                 SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set default voice");
334         }
335
336         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
337         SLOG(LOG_DEBUG, TAG_TTSC, " ");
338     
339         return ret;
340 }
341
342
343 int tts_setting_get_default_speed(tts_setting_speed_e* speed)
344 {
345         SLOG(LOG_DEBUG, TAG_TTSC, "===== Get default speed");
346
347         if (TTS_SETTING_STATE_NONE == g_state) {
348                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized");
349                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
350                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
351                 return TTS_SETTING_ERROR_INVALID_STATE;
352         }
353
354         if (NULL == speed) {
355                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Param is NULL");
356                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
357                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
358                 return TTS_SETTING_ERROR_INVALID_PARAMETER;
359         }
360
361         int temp;
362         temp = 0;
363
364         int ret = tts_setting_dbus_request_get_default_speed(&temp);
365         if (0 != ret) {
366                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret);
367         } else {
368                 /* Copy value */
369                 *speed = (tts_setting_speed_e)temp;
370                 SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Get default speed : %d ", (int)*speed);
371         }
372
373         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
374         SLOG(LOG_DEBUG, TAG_TTSC, " ");
375
376         return ret;
377 }
378
379
380 int tts_setting_set_default_speed(tts_setting_speed_e speed)
381 {
382         SLOG(LOG_DEBUG, TAG_TTSC, "===== Set default speed");
383
384         if (TTS_SETTING_STATE_NONE == g_state) {
385                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized");
386                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
387                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
388                 return TTS_SETTING_ERROR_INVALID_STATE;
389         }
390
391         if (speed < TTS_SETTING_SPEED_VERY_SLOW || TTS_SETTING_SPEED_VERY_FAST < speed) {
392                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Invalid speed");
393                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
394                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
395                 return TTS_SETTING_ERROR_INVALID_PARAMETER;
396         }
397
398         int ret = tts_setting_dbus_request_set_default_speed((int)speed);
399         if (0 != ret) {
400                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret);
401         } else {
402                 SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set default speed");
403         }
404         
405         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
406         SLOG(LOG_DEBUG, TAG_TTSC, " ");
407
408         return ret;
409 }
410
411 int tts_setting_foreach_engine_settings(tts_setting_engine_setting_cb callback, void* user_data)
412 {
413         SLOG(LOG_DEBUG, TAG_TTSC, "===== Foreach engine setting");
414
415         if (TTS_SETTING_STATE_NONE == g_state) {
416                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized");
417                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
418                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
419                 return TTS_SETTING_ERROR_INVALID_STATE;
420         }
421
422         if (NULL == callback) {
423                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is NULL");
424                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
425                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
426                 return TTS_SETTING_ERROR_INVALID_PARAMETER;
427         }
428
429         int ret = tts_setting_dbus_request_get_engine_setting(callback, user_data);
430         if (0 != ret) {
431                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret);
432         } else {
433                 SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Foreach engine setting");
434         }
435
436         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
437         SLOG(LOG_DEBUG, TAG_TTSC, " ");
438
439         return ret;
440 }
441
442 int tts_setting_set_engine_setting(const char* key, const char* value)
443 {
444         SLOG(LOG_DEBUG, TAG_TTSC, "===== Set engine setting");
445
446         if (TTS_SETTING_STATE_NONE == g_state) {
447                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized");
448                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
449                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
450                 return TTS_SETTING_ERROR_INVALID_STATE;
451         }
452
453         if(NULL == key || NULL == value) {
454                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Param is NULL");
455                 SLOG(LOG_DEBUG, TAG_TTSC, "=====");
456                 SLOG(LOG_DEBUG, TAG_TTSC, " ");
457                 return TTS_SETTING_ERROR_INVALID_PARAMETER;
458         }
459
460         int ret = tts_setting_dbus_request_set_engine_setting(key, value);
461         if (0 != ret) {
462                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret);
463         } else {
464                 SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Foreach engine setting");
465         }
466
467         SLOG(LOG_DEBUG, TAG_TTSC, "=====");
468         SLOG(LOG_DEBUG, TAG_TTSC, " ");
469
470         return ret;
471 }
472
473 int __setting_get_cmd_line(char *file, char *buf) 
474 {
475         FILE *fp = NULL;
476
477         fp = fopen(file, "r");
478         if (fp == NULL) {
479                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get command line");
480                 return -1;
481         }
482
483         memset(buf, 0, 256);
484         if (NULL == fgets(buf, 256, fp)) {
485                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail fgets command line");
486                 fclose(fp);
487                 return -1;
488         }
489         fclose(fp);
490
491         return 0;
492 }
493
494 /* Functions for tts-daemon fork */
495 static bool __tts_setting_is_alive()
496 {
497         DIR *dir;
498         struct dirent *entry;
499         struct stat filestat;
500         
501         int pid;
502         char cmdLine[256];
503         char tempPath[256];
504
505         dir  = opendir("/proc");
506         if (NULL == dir) {
507                 SLOG(LOG_ERROR, TAG_TTSC, "process checking is FAILED");
508                 return FALSE;
509         }
510
511         while ((entry = readdir(dir)) != NULL) {
512                 if (0 != lstat(entry->d_name, &filestat))
513                         continue;
514
515                 if (!S_ISDIR(filestat.st_mode))
516                         continue;
517
518                 pid = atoi(entry->d_name);
519                 if (pid <= 0) continue;
520
521                 sprintf(tempPath, "/proc/%d/cmdline", pid);
522                 if (0 != __setting_get_cmd_line(tempPath, cmdLine)) {
523                         continue;
524                 }
525
526                 if (0 == strncmp(cmdLine, "[tts-daemon]", strlen("[tts-daemon]")) ||
527                         0 == strncmp(cmdLine, "tts-daemon", strlen("tts-daemon")) ||
528                         0 == strncmp(cmdLine, "/usr/bin/tts-daemon", strlen("/usr/bin/tts-daemon"))) {
529                                 SLOG(LOG_DEBUG, TAG_TTSC, "tts-daemon is ALIVE !!");
530                                 closedir(dir);
531                                 return TRUE;
532                 }
533         }
534         SLOG(LOG_DEBUG, TAG_TTSC, "THERE IS NO tts-daemon !!");
535
536         closedir(dir);
537         return FALSE;
538
539 }
540
541 static int __check_setting_tts_daemon()
542 {
543         if( TRUE == __tts_setting_is_alive() )
544                 return 0;
545
546         /* fork-exec tts-daemom */
547         int pid, i;
548
549         pid = fork();
550
551         switch(pid) {
552         case -1:
553                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create tts-daemon ");
554                 break;
555
556         case 0:
557                 setsid();
558                 for( i = 0 ; i < _NSIG ; i++ )
559                         signal(i, SIG_DFL);
560
561                 execl("/usr/bin/tts-daemon", "/usr/bin/tts-daemon", NULL);
562                 break;
563
564         default:
565                 break;
566         }
567
568         return 0;
569 }