apply same traits for CHECK_BOX and RADIO_BUTTON
[profile/tv/apps/native/screen-reader.git] / src / screen_reader_tts.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define _GNU_SOURCE
18
19 #include <Ecore.h>
20 #include "screen_reader_tts.h"
21 #include "screen_reader_vconf.h"
22 #include "logger.h"
23
24 // ---------------------------- DEBUG HELPERS ------------------------------
25
26 #define FLUSH_LIMIT 1
27
28 static int last_utt_id;
29 static Eina_Bool pause_state = EINA_FALSE;
30 static Eina_Bool flush_flag = EINA_FALSE;
31 static Eina_Strbuf *txt_keep_buff = NULL;
32
33 static void (*on_utterance_end) (void);
34
35 static void _text_keep(const char *txt)
36 {
37         if (!txt_keep_buff)
38                 return;
39         if (eina_strbuf_length_get(txt_keep_buff) > 0)
40                 eina_strbuf_append(txt_keep_buff, ", ");
41         eina_strbuf_append(txt_keep_buff, txt);
42 }
43
44 static char *get_tts_error(int r)
45 {
46         switch (r) {
47         case TTS_ERROR_NONE:
48                 {
49                         return "no error";
50                 }
51         case TTS_ERROR_INVALID_PARAMETER:
52                 {
53                         return "inv param";
54                 }
55         case TTS_ERROR_OUT_OF_MEMORY:
56                 {
57                         return "out of memory";
58                 }
59         case TTS_ERROR_OPERATION_FAILED:
60                 {
61                         return "oper failed";
62                 }
63         case TTS_ERROR_INVALID_STATE:
64                 {
65                         return "inv state";
66                 }
67         default:
68                 {
69                         return "uknown error";
70                 }
71         }
72 }
73
74 static char *get_tts_state(tts_state_e r)
75 {
76         switch (r) {
77         case TTS_STATE_CREATED:
78                 {
79                         return "created";
80                 }
81         case TTS_STATE_READY:
82                 {
83                         return "ready";
84                 }
85         case TTS_STATE_PLAYING:
86                 {
87                         return "playing";
88                 }
89         case TTS_STATE_PAUSED:
90                 {
91                         return "pause";
92                 }
93         default:
94                 {
95                         return "uknown state";
96                 }
97         }
98 }
99
100 //-------------------------------------------------------------------------------------------------
101
102 void set_utterance_cb(void (*uter_cb) (void))
103 {
104         on_utterance_end = uter_cb;
105 }
106
107 bool get_supported_voices_cb(tts_h tts, const char *language, int voice_type, void *user_data)
108 {
109         DEBUG("LANG: %s; TYPE: %d", language, voice_type);
110
111         Service_Data *sd = user_data;
112         Voice_Info *vi = calloc(1, sizeof(Voice_Info));
113         if (!vi) {
114                 ERROR(MEMORY_ERROR);
115                 return ECORE_CALLBACK_CANCEL;
116         }
117
118         if (asprintf(&vi->language, "%s", language) < 0) {
119                 free(vi);
120                 ERROR(MEMORY_ERROR);
121                 return ECORE_CALLBACK_CANCEL;
122         }
123
124         vi->voice_type = voice_type;
125
126         sd->available_languages = eina_list_append(sd->available_languages, vi);
127
128         return ECORE_CALLBACK_RENEW;
129 }
130
131 static void __tts_test_utt_started_cb(tts_h tts, int utt_id, void *user_data)
132 {
133         DEBUG("Utterance started : utt id(%d) \n", utt_id);
134         return;
135 }
136
137 static void __tts_test_utt_completed_cb(tts_h tts, int utt_id, void *user_data)
138 {
139         DEBUG("Utterance completed : utt id(%d) \n", utt_id);
140         if (last_utt_id - utt_id > FLUSH_LIMIT)
141                 flush_flag = EINA_TRUE;
142         else {
143                 if (flush_flag)
144                         flush_flag = EINA_FALSE;
145         }
146
147         if (last_utt_id == utt_id) {
148                 DEBUG("LAST UTTERANCE");
149                 pause_state = EINA_FALSE;
150                 on_utterance_end();
151         }
152
153         return;
154 }
155
156 bool tts_init(void *data)
157 {
158         DEBUG("--------------------- TTS_init START ---------------------");
159         Service_Data *sd = data;
160
161         int r = tts_create(&sd->tts);
162         DEBUG("Create tts %d (%s)", r, get_tts_error(r));
163
164         r = tts_set_mode(sd->tts, TTS_MODE_SCREEN_READER);
165         DEBUG("Set tts mode SR %d (%s)", r, get_tts_error(r));
166
167         r = tts_prepare(sd->tts);
168         DEBUG("Prepare tts %d (%s)", r, get_tts_error(r));
169
170         tts_set_state_changed_cb(sd->tts, state_changed_cb, sd);
171
172         tts_set_utterance_started_cb(sd->tts, __tts_test_utt_started_cb, sd);
173         tts_set_utterance_completed_cb(sd->tts, __tts_test_utt_completed_cb, sd);
174
175         DEBUG("---------------------- TTS_init END ----------------------\n\n");
176         txt_keep_buff = eina_strbuf_new();
177         return true;
178 }
179
180 Eina_Bool tts_pause_get(void)
181 {
182         DEBUG("PAUSE STATE: %d", pause_state);
183         return pause_state;
184 }
185
186 void tts_stop_set(void)
187 {
188         Service_Data *sd = get_pointer_to_service_data_struct();
189         tts_stop(sd->tts);
190 }
191
192 Eina_Bool tts_pause_set(Eina_Bool pause_switch)
193 {
194         Service_Data *sd = get_pointer_to_service_data_struct();
195         if (!sd)
196                 return EINA_FALSE;
197
198         if (pause_switch) {
199                 pause_state = EINA_TRUE;
200
201                 if (tts_pause(sd->tts)) {
202                         pause_state = EINA_FALSE;
203                         return EINA_FALSE;
204                 }
205         } else if (!pause_switch) {
206                 pause_state = EINA_FALSE;
207
208                 if (tts_play(sd->tts)) {
209                         pause_state = EINA_TRUE;
210                         return EINA_FALSE;
211                 }
212         }
213         return EINA_TRUE;
214 }
215
216 void tts_speak(char *text_to_speak, Eina_Bool flush_switch)
217 {
218         int ret = 0;
219         Service_Data *sd = get_pointer_to_service_data_struct();
220         int speak_id;
221
222         if (!sd)
223                 return;
224         tts_state_e state;
225         tts_get_state(sd->tts, &state);
226
227         if (state != TTS_STATE_PLAYING && state != TTS_STATE_PAUSED && state != TTS_STATE_READY) {
228                 if (text_to_speak)
229                         _text_keep(text_to_speak);
230                 return;
231         }
232
233         if (flush_flag || flush_switch) {
234                 if (state == TTS_STATE_PLAYING || state == TTS_STATE_PAUSED) {
235                         ret = tts_stop(sd->tts);
236                         if (TTS_ERROR_NONE != ret) {
237                                 DEBUG("Fail to stop TTS: resultl(%d)", ret);
238                         }
239                 }
240         }
241
242         DEBUG("tts_speak\n");
243         DEBUG("text to say:%s\n", text_to_speak);
244         if (!text_to_speak)
245                 return;
246         if (!text_to_speak[0])
247                 return;
248
249         if ((ret = tts_add_text(sd->tts, text_to_speak, NULL, TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &speak_id))) {
250                 switch (ret) {
251                 case TTS_ERROR_INVALID_PARAMETER:
252                         DEBUG("FAILED tts_add_text: error: TTS_ERROR_INVALID_PARAMETER");
253                         break;
254                 case TTS_ERROR_INVALID_STATE:
255                         DEBUG("FAILED tts_add_text: error: TTS_ERROR_INVALID_STATE, tts_state: %d", state);
256                         break;
257                 case TTS_ERROR_INVALID_VOICE:
258                         DEBUG("FAILED tts_add_text: error: TTS_ERROR_INVALID_VOICE");
259                         break;
260                 case TTS_ERROR_OPERATION_FAILED:
261                         DEBUG("FAILED tts_add_text: error: TTS_ERROR_OPERATION_FAILED");
262                         break;
263                 case TTS_ERROR_NOT_SUPPORTED:
264                         DEBUG("FAILED tts_add_text: error: TTS_ERROR_NOT_SUPPORTED");
265                         break;
266                 default:
267                         DEBUG("FAILED tts_add_text: error: not recognized");
268                 }
269                 return;
270         }
271
272         DEBUG("added id to:%d\n", speak_id);
273         last_utt_id = speak_id;
274 }
275
276 Eina_Bool update_supported_voices(void *data)
277 {
278         DEBUG("START");
279         tts_state_e state;
280
281         Service_Data *sd = data;
282
283         int res = tts_get_state(sd->tts, &state);
284
285         if (res != TTS_ERROR_NONE) {
286                 DEBUG("CANNOT RETRIVE STATE");
287                 return EINA_FALSE;
288         }
289
290         if (state == TTS_STATE_READY) {
291                 tts_foreach_supported_voices(sd->tts, get_supported_voices_cb, sd);
292         } else {
293                 sd->update_language_list = EINA_TRUE;
294         }
295
296         DEBUG("END")
297                 return EINA_TRUE;
298 }
299
300 void state_changed_cb(tts_h tts, tts_state_e previous, tts_state_e current, void *user_data)
301 {
302         if (pause_state) {
303                 DEBUG("TTS is currently paused. Resume to start reading");
304                 return;
305         }
306
307         DEBUG("++++++++++++++++state_changed_cb\n++++++++++++++++++");
308         DEBUG("current state:%s and previous state:%s\n", get_tts_state(current), get_tts_state(previous));
309         Service_Data *sd = user_data;
310
311         if (TTS_STATE_CREATED == previous && TTS_STATE_READY == current) {
312
313                 update_supported_voices(sd);
314
315                 char *txt;
316
317                 if (!txt_keep_buff)
318                         return;
319                 if (!eina_strbuf_length_get(txt_keep_buff))
320                         return;
321
322                 txt = eina_strbuf_string_steal(txt_keep_buff);
323                 eina_strbuf_free(txt_keep_buff);
324                 txt_keep_buff = NULL;
325
326                 tts_speak(txt, EINA_FALSE);
327                 tts_play(sd->tts);
328                 free(txt);
329         } else if (current == TTS_STATE_READY || current == TTS_STATE_PAUSED) {
330                 DEBUG("TTS state == %s!", get_tts_state(current));
331                 tts_play(sd->tts);
332         } else {
333                 DEBUG("TTS state != ready or paused!\n");
334         }
335 }
336
337 void spi_stop(void *data)
338 {
339         if (!data) {
340                 ERROR("Invalid parameter");
341                 return;
342         }
343
344         Service_Data *sd = data;
345         sd->update_language_list = false;
346         free((char *)sd->text_from_dbus);
347         free(sd->current_value);
348         sd->text_from_dbus = NULL;
349         sd->current_value = NULL;
350         tts_stop(sd->tts);
351 }