2 * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://floralicense.org/license/
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.
20 #include "screen_reader_tts.h"
21 #include "screen_reader_vconf.h"
24 // ---------------------------- DEBUG HELPERS ------------------------------
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;
33 static void (*on_utterance_end) (void);
35 static void _text_keep(const char *txt)
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);
44 static char *get_tts_error(int r)
51 case TTS_ERROR_INVALID_PARAMETER:
55 case TTS_ERROR_OUT_OF_MEMORY:
57 return "out of memory";
59 case TTS_ERROR_OPERATION_FAILED:
63 case TTS_ERROR_INVALID_STATE:
69 return "uknown error";
74 static char *get_tts_state(tts_state_e r)
77 case TTS_STATE_CREATED:
85 case TTS_STATE_PLAYING:
89 case TTS_STATE_PAUSED:
95 return "uknown state";
100 //-------------------------------------------------------------------------------------------------
102 void set_utterance_cb(void (*uter_cb) (void))
104 on_utterance_end = uter_cb;
107 bool get_supported_voices_cb(tts_h tts, const char *language, int voice_type, void *user_data)
109 DEBUG("LANG: %s; TYPE: %d", language, voice_type);
111 Service_Data *sd = user_data;
112 Voice_Info *vi = calloc(1, sizeof(Voice_Info));
115 return ECORE_CALLBACK_CANCEL;
118 if (asprintf(&vi->language, "%s", language) < 0) {
121 return ECORE_CALLBACK_CANCEL;
124 vi->voice_type = voice_type;
126 sd->available_languages = eina_list_append(sd->available_languages, vi);
128 return ECORE_CALLBACK_RENEW;
131 static void __tts_test_utt_started_cb(tts_h tts, int utt_id, void *user_data)
133 DEBUG("Utterance started : utt id(%d) \n", utt_id);
137 static void __tts_test_utt_completed_cb(tts_h tts, int utt_id, void *user_data)
139 DEBUG("Utterance completed : utt id(%d) \n", utt_id);
140 if (last_utt_id - utt_id > FLUSH_LIMIT)
141 flush_flag = EINA_TRUE;
144 flush_flag = EINA_FALSE;
147 if (last_utt_id == utt_id) {
148 DEBUG("LAST UTTERANCE");
149 pause_state = EINA_FALSE;
156 bool tts_init(void *data)
158 DEBUG("--------------------- TTS_init START ---------------------");
159 Service_Data *sd = data;
161 int r = tts_create(&sd->tts);
162 DEBUG("Create tts %d (%s)", r, get_tts_error(r));
164 r = tts_set_mode(sd->tts, TTS_MODE_SCREEN_READER);
165 DEBUG("Set tts mode SR %d (%s)", r, get_tts_error(r));
167 r = tts_prepare(sd->tts);
168 DEBUG("Prepare tts %d (%s)", r, get_tts_error(r));
170 tts_set_state_changed_cb(sd->tts, state_changed_cb, sd);
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);
175 DEBUG("---------------------- TTS_init END ----------------------\n\n");
176 txt_keep_buff = eina_strbuf_new();
180 Eina_Bool tts_pause_get(void)
182 DEBUG("PAUSE STATE: %d", pause_state);
186 void tts_stop_set(void)
188 Service_Data *sd = get_pointer_to_service_data_struct();
192 Eina_Bool tts_pause_set(Eina_Bool pause_switch)
194 Service_Data *sd = get_pointer_to_service_data_struct();
199 pause_state = EINA_TRUE;
201 if (tts_pause(sd->tts)) {
202 pause_state = EINA_FALSE;
205 } else if (!pause_switch) {
206 pause_state = EINA_FALSE;
208 if (tts_play(sd->tts)) {
209 pause_state = EINA_TRUE;
216 void tts_speak(char *text_to_speak, Eina_Bool flush_switch)
219 Service_Data *sd = get_pointer_to_service_data_struct();
225 tts_get_state(sd->tts, &state);
227 if (state != TTS_STATE_PLAYING && state != TTS_STATE_PAUSED && state != TTS_STATE_READY) {
229 _text_keep(text_to_speak);
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);
242 DEBUG("tts_speak\n");
243 DEBUG("text to say:%s\n", text_to_speak);
246 if (!text_to_speak[0])
249 if ((ret = tts_add_text(sd->tts, text_to_speak, NULL, TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &speak_id))) {
251 case TTS_ERROR_INVALID_PARAMETER:
252 DEBUG("FAILED tts_add_text: error: TTS_ERROR_INVALID_PARAMETER");
254 case TTS_ERROR_INVALID_STATE:
255 DEBUG("FAILED tts_add_text: error: TTS_ERROR_INVALID_STATE, tts_state: %d", state);
257 case TTS_ERROR_INVALID_VOICE:
258 DEBUG("FAILED tts_add_text: error: TTS_ERROR_INVALID_VOICE");
260 case TTS_ERROR_OPERATION_FAILED:
261 DEBUG("FAILED tts_add_text: error: TTS_ERROR_OPERATION_FAILED");
263 case TTS_ERROR_NOT_SUPPORTED:
264 DEBUG("FAILED tts_add_text: error: TTS_ERROR_NOT_SUPPORTED");
267 DEBUG("FAILED tts_add_text: error: not recognized");
272 DEBUG("added id to:%d\n", speak_id);
273 last_utt_id = speak_id;
276 Eina_Bool update_supported_voices(void *data)
281 Service_Data *sd = data;
283 int res = tts_get_state(sd->tts, &state);
285 if (res != TTS_ERROR_NONE) {
286 DEBUG("CANNOT RETRIVE STATE");
290 if (state == TTS_STATE_READY) {
291 tts_foreach_supported_voices(sd->tts, get_supported_voices_cb, sd);
293 sd->update_language_list = EINA_TRUE;
300 void state_changed_cb(tts_h tts, tts_state_e previous, tts_state_e current, void *user_data)
303 DEBUG("TTS is currently paused. Resume to start reading");
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;
311 if (TTS_STATE_CREATED == previous && TTS_STATE_READY == current) {
313 update_supported_voices(sd);
319 if (!eina_strbuf_length_get(txt_keep_buff))
322 txt = eina_strbuf_string_steal(txt_keep_buff);
323 eina_strbuf_free(txt_keep_buff);
324 txt_keep_buff = NULL;
326 tts_speak(txt, EINA_FALSE);
329 } else if (current == TTS_STATE_READY || current == TTS_STATE_PAUSED) {
330 DEBUG("TTS state == %s!", get_tts_state(current));
333 DEBUG("TTS state != ready or paused!\n");
337 void spi_stop(void *data)
340 ERROR("Invalid parameter");
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;