modules/information/ext_storage: fix sigsegv
[apps/core/preloaded/indicator-win.git] / src / tts.c
1 /*
2  *  Indicator
3  *
4  * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20
21
22 #ifdef _SUPPORT_SCREEN_READER2
23
24 #include <tts.h>
25 #include <vconf.h>
26 #include <vconf-keys.h>
27 #include "main.h"
28 #include "common.h"
29 #include "tts.h"
30
31 static void _tts_init(void);
32 static void _tts_fini(void);
33
34 static struct _s_info {
35         tts_h tts_handler;
36         Eina_List *list;
37 } s_info = {
38         .tts_handler = NULL,
39         .list = NULL,
40 };
41
42 typedef struct _QP_TTS {
43         int id;
44         int done;
45         char *message;
46 } QP_TTS_T;
47
48
49
50 static QP_TTS_T * _tts_entry_new(int id, char *message)
51 {
52         QP_TTS_T *entry = NULL;
53         retif(message == NULL, NULL, "NULL message");
54
55         entry = (QP_TTS_T *)calloc(1, sizeof(QP_TTS_T));
56         retif(entry == NULL, NULL, "failed to memory allocation");
57
58         entry->id = id;
59         entry->message = strdup(message);
60
61         return entry;
62 }
63
64
65
66 static void  _tts_entry_del(QP_TTS_T *entry)
67 {
68         retif(entry == NULL, ,"invalid parameter");
69
70         if (entry->message != NULL) {
71                 free(entry->message);
72         }
73
74         free(entry);
75 }
76
77
78
79 static QP_TTS_T *_tts_list_get_first(void)
80 {
81         return eina_list_nth(s_info.list, 0);
82 }
83
84
85
86 static void _tts_list_add(QP_TTS_T *entry)
87 {
88         retif(entry == NULL, ,"invalid parameter");
89
90         s_info.list = eina_list_prepend(s_info.list, entry);
91 }
92
93
94
95 static void _tts_list_del(QP_TTS_T *entry)
96 {
97         retif(entry == NULL, ,"invalid parameter");
98
99         s_info.list = eina_list_remove(s_info.list, entry);
100 }
101
102
103
104 static void _tts_list_clean(void)
105 {
106         QP_TTS_T *entry = NULL;
107
108         while ((entry = _tts_list_get_first()) != NULL) {
109                  _tts_list_del(entry);
110                  _tts_entry_del(entry);
111         }
112 }
113
114
115
116 static int _is_screenreader_on(void)
117 {
118         int ret = -1, status = 0;
119
120         ret = vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &status);
121         retif(ret != 0, 0, "failed to read VCONFKEY_SETAPPL_ACCESSIBILITY_TTS %d", ret);
122
123         return status;
124 }
125
126
127
128 static tts_state_e _tts_state_get(void)
129 {
130         int ret = TTS_ERROR_NONE;
131         tts_state_e state = TTS_STATE_READY;
132
133         if (s_info.tts_handler != NULL) {
134                 ret = tts_get_state(s_info.tts_handler, &state);
135                 if (TTS_ERROR_NONE != ret){
136                         ERR("get state error(%d)", ret);
137                         return -1;
138                 }
139
140                 return state;
141         }
142
143         return -1;
144 }
145
146
147
148 static void _tts_play(const char *message)
149 {
150         int utt = 0;
151         int ret = TTS_ERROR_NONE;
152
153         if (s_info.tts_handler == NULL) {
154                 ERR("critical, TTS handler isn't initialized");
155                 return;
156         }
157
158         DBG("adding %s", message);
159
160         ret = tts_add_text(s_info.tts_handler, message, NULL, TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &utt);
161         if (TTS_ERROR_NONE != ret){
162                 ERR("add text error!");
163                 return;
164         }
165
166         ret = tts_play(s_info.tts_handler);
167         if(ret != TTS_ERROR_NONE) {
168                 ERR("play error(%d) state(%d)", ret);
169         }
170 }
171
172
173
174 static void _tts_stop(void)
175 {
176         int ret = TTS_ERROR_NONE;
177
178         if (s_info.tts_handler == NULL) {
179                 ERR("critical, TTS handler isn't initialized");
180                 return;
181         }
182
183         ret = tts_stop(s_info.tts_handler);
184         if (TTS_ERROR_NONE != ret){
185                 ERR("failed to stop play:%d", ret);
186                 return;
187         }
188 }
189
190
191
192 static void _tts_state_changed_cb(tts_h tts, tts_state_e previous, tts_state_e current, void* user_data)
193 {
194         QP_TTS_T *entry = NULL;
195
196         DBG("_tts_state_changed_cb(%d => %d)", previous, current);
197
198         if(previous == TTS_STATE_CREATED && current == TTS_STATE_READY) {
199                 entry = _tts_list_get_first();
200                 if (entry != NULL) {
201                          _tts_play(entry->message);
202                          _tts_list_del(entry);
203                          _tts_entry_del(entry);
204                 }
205                 _tts_list_clean();
206         }
207 }
208
209
210
211 static void _tts_utt_started_cb(tts_h tts, int utt_id, void *user_data)
212 {
213         DBG("_tts_utt_started_cb");
214 }
215
216
217
218 static void _tts_utt_completed_cb(tts_h tts, int utt_id, void *user_data)
219 {
220         DBG("_tts_utt_completed_cb");
221 }
222
223
224
225 static void _tts_error_cb(tts_h tts, int utt_id, tts_error_e reason, void* user_data)
226 {
227         DBG("_tts_error_cb");
228 }
229
230
231
232 static int _tts_callback_set(tts_h tts, void* data)
233 {
234         int ret = 0;
235
236         if (TTS_ERROR_NONE != (ret = tts_set_state_changed_cb(tts, _tts_state_changed_cb, tts))){
237                 ERR("set interrupted callback error !!:%d", ret);
238                 ret = -1;
239         }
240
241         if (TTS_ERROR_NONE != (ret = tts_set_utterance_started_cb(tts, _tts_utt_started_cb, data))) {
242                 ERR("set utterance started callback error !!:%d", ret);
243                 ret = -1;
244         }
245
246         if (TTS_ERROR_NONE != (ret = tts_set_utterance_completed_cb(tts, _tts_utt_completed_cb, data))) {
247                 ERR("set utterance completed callback error !!:%d", ret);
248                 ret = -1;
249         }
250
251         if (TTS_ERROR_NONE != (ret = tts_set_error_cb(tts, _tts_error_cb, data))) {
252                 ERR("set error callback error !!:%d", ret);
253                 ret = -1;
254         }
255
256         return ret;
257 }
258
259
260
261 static void _tts_init()
262 {
263         tts_h tts = NULL;
264         int ret = TTS_ERROR_NONE;
265
266         if (s_info.tts_handler == NULL) {
267                 ret = tts_create(&tts);
268                 if(ret != TTS_ERROR_NONE) {
269                         ERR("tts_create() failed");
270                         return ;
271                 }
272
273                 ret = tts_set_mode(tts, TTS_MODE_NOTIFICATION);
274                 if(ret != TTS_ERROR_NONE) {
275                         ERR("tts_create() failed");
276                         tts_destroy(s_info.tts_handler);
277                         s_info.tts_handler = NULL;
278                         return ;
279                 }
280
281                 if(_tts_callback_set(tts, NULL) != 0) {
282                         ERR("_tts_callback_set() failed");
283                         tts_destroy(s_info.tts_handler);
284                         s_info.tts_handler = NULL;
285                         return ;
286                 }
287
288                 ret = tts_prepare(tts);
289                 if(ret != TTS_ERROR_NONE) {
290                         ERR("tts_create() failed");
291                         tts_destroy(s_info.tts_handler);
292                         s_info.tts_handler = NULL;
293                         return ;
294                 }
295
296                 s_info.tts_handler = tts;
297         }
298 }
299
300
301
302 static void _tts_fini(void)
303 {
304         int ret = TTS_ERROR_NONE;
305
306         if (s_info.tts_handler != NULL) {
307                 ret = tts_destroy(s_info.tts_handler);
308                 if(ret != TTS_ERROR_NONE) {
309                         ERR("tts_destroy() failed");
310                 }
311                 s_info.tts_handler = NULL;
312         }
313 }
314
315
316
317 static void _tts_vconf_cb(keynode_t *key, void *data){
318         if(_is_screenreader_on() == 0) {
319                 DBG("TTS turned off");
320                 _tts_fini();
321         }
322
323         _tts_list_clean();
324 }
325
326
327
328 void indicator_service_tts_init(void *data) {
329         int ret = 0;
330
331     ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS,
332                 _tts_vconf_cb, data);
333 }
334
335
336
337 void indicator_service_tts_fini(void *data) {
338         int ret = 0;
339
340     ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS,
341                 _tts_vconf_cb, data);
342
343     _tts_list_clean();
344 }
345
346
347
348 void indicator_service_tts_play(char *message) {
349         tts_state_e state = 0;
350         QP_TTS_T *entry = NULL;
351         retif(message == NULL, ,"invalid parameter");
352
353         if (_is_screenreader_on() == 1) {
354                 _tts_init();
355
356                 state = _tts_state_get();
357
358                 if (state == TTS_STATE_CREATED) {
359                         _tts_list_clean();
360                         entry = _tts_entry_new(-1, message);
361                         if (entry != NULL) {
362                                  _tts_list_add(entry);
363                         }
364                 } else if (state == TTS_STATE_PLAYING || state == TTS_STATE_PAUSED) {
365                         _tts_stop();
366                         _tts_play(message);
367                 } else if (state == TTS_STATE_READY) {
368                         _tts_play(message);
369                 } else {
370                         ERR("invalid status: %d", state);
371                 }
372         }
373 }
374 #endif /* _SUPPORT_SCREEN_READER2 */