[screen reader] Code refactoring: tts 37/239637/11 accepted/tizen/unified/20200803.122203 submit/tizen/20200802.221805
authorBartlomiej Grzelewski <b.grzelewski@samsung.com>
Tue, 28 Jul 2020 09:10:47 +0000 (11:10 +0200)
committerBartlomiej Grzelewski <b.grzelewski@samsung.com>
Fri, 31 Jul 2020 08:53:47 +0000 (10:53 +0200)
* change function prefix from tts to tw (Tts Wrapper)
  as tts is reserved by system service
* reduce number of global values in tw module

Change-Id: I38a30734f79fbf53ddb316071464eba126a93336

12 files changed:
include/screen_reader.h
include/screen_reader_tts.h
src/app_tracker.c
src/dbus_direct_reading_adapter.c
src/granularity_read.c
src/keyboard_tracker.c
src/main.c
src/navigator.c
src/screen_reader.c
src/screen_reader_spi.c
src/screen_reader_system.c
src/screen_reader_tts.c

index 24803ff844ed03286de52e3c643312759819576c..8493e6755cac1c98ad1ff34226df32b15ff38d98 100644 (file)
@@ -40,14 +40,6 @@ typedef struct _Service_Data
        //Set by vconf
        bool run_service;
 
-       //Set by tts
-       tts_h tts;
-       Eina_List *available_languages;
-
-       char *text_to_say_info;
-       char *current_value;
-       char *current_char;
-
        //Actions to do when tts state is 'ready'
        int _dbus_txt_readed;
        bool say_text;
index 4d6ee3a5edd0b1e246e32abd4f4e42b19003be33..c774815c0b56d1a0cf9213df34bea73ebb20b8df 100644 (file)
@@ -41,18 +41,20 @@ typedef struct {
        Eina_Bool is_screen_turn_off;
 } Read_Command;
 
+typedef void (*utterance_cb_t)(void*);
+
 /**
- * @brief Initializes Text To Speech (TTS) service for the screen reader
+ * @brief Initializes Text To Speech Wraper (TW) module. This module is used to pass
+ *        requests to Text To Speech (TTS) service.
  * @param data screen reader internal data struct
  */
-bool tts_init(void *data);
+bool tw_init(void);
 
 /**
- * @brief Disables Text To Speech (TTS) service
+ * @brief Disables Text To Speech Wrapper (TW) module.
  * @param data screen reader internal data struct
  */
-void tts_shutdown(void *data);
-
+void tw_shutdown(void);
 
 /**
  * @brief Requests discardable, asynchronous (queued) reading of given text.
@@ -63,7 +65,7 @@ void tts_shutdown(void *data);
  *
  * @note returns NULL if provided text is NULL or field "tts" in Service Data is unset
  */
-Read_Command *tts_speak(char *text_to_speak, Eina_Bool want_discard_previous_reading);
+Read_Command *tw_speak(char *text_to_speak, Eina_Bool want_discard_previous_reading);
 
 //TODO: add support for i18
 /**
@@ -78,19 +80,19 @@ Read_Command *tts_speak(char *text_to_speak, Eina_Bool want_discard_previous_rea
  * @return Read_Command* a pointer to the reading command suppporting this reading request
  *
  */
-Read_Command *tts_speak_customized(char *text_to_speak, Eina_Bool want_discard_previous_reading, Eina_Bool discardable, AtspiAccessible *obj, unsigned int delay);
+Read_Command *tw_speak_customized(char *text_to_speak, Eina_Bool want_discard_previous_reading, Eina_Bool discardable, AtspiAccessible *obj, unsigned int delay);
 
 /**
  * @brief Purges commands from local queue and stops current reading.
  * If only_discardables is set to true, then only discardables are purged.
  * Also current reading then will be only stopped, if its discardable.
  */
-void tts_purge(Eina_Bool only_discardables);
+void tw_purge(Eina_Bool only_discardables);
 
 /*
  * @brief Stops playing the utterance and clears first element from queue.
  */
-void tts_stop_set(void);
+void tw_stop_set(void);
 
 /*
  * @brief Checks if reading out in screen reader is in pause state
@@ -101,26 +103,20 @@ void tts_stop_set(void);
  *
  * @see tts_pause_set()
  */
-Eina_Bool tts_pause_get(void);
+Eina_Bool tw_pause_get(void);
 
 /*
  * @brief Freezes or resumes the utterance
  * @return EINA_TRUE state was successfully changed, EINA_FALSE otherwise
  */
-Eina_Bool tts_pause_set(Eina_Bool pause_switch);
+Eina_Bool tw_pause_set(Eina_Bool pause_switch);
 
 /*
  * @brief Sets callback being invoked after end of utterance
  * @param utter_cb pointer to callback function
  * @param user_data data to pass to callback function
+ * @param deleter function calls to clean up user_data when utter_cb is overwritten
  */
-void set_utterance_cb(void(*utter_cb)(void*), void* user_data);
-
-/*
- * @brief Remove callback being invoked after end of utterance
- *        This function allows to gracefully free user_data.
- * @return user_data
- */
-void* remove_utterance_cb();
+void tw_set_utterance_cb(utterance_cb_t utter_cb, void* user_data, utterance_cb_t deleter);
 
 #endif /* SCREEN_READER_TTS_H_ */
index 6e14ea72b86746293616d785aaf4b0c662f44250..b695171126e010768d3c4902a05b476f2ef216d4 100644 (file)
@@ -123,7 +123,7 @@ static gboolean _on_timeout_rebuild_navigation_context(gpointer user_data)
                }
 
                if (default_label_enabled)
-                       tts_purge(EINA_TRUE);
+                       tw_purge(EINA_TRUE);
 
                gchar *id = atspi_accessible_get_unique_id(root, NULL);
                DEBUG("Rebuilding navigation context - root: %s, role: %d, default_label_enabled : %s", id, role, default_label_enabled ? "true" : "false");
@@ -165,7 +165,7 @@ static void _read_value(AtspiValue *value)
        g_snprintf(buf_percent, sizeof(buf_percent), "%d", percent);
        SUPPRESS_FORMAT_ERROR(g_snprintf(buf, sizeof(buf), _("IDS_GCTS_OPT_P1SS_PERCENT_TTS"), buf_percent));
        DEBUG("has value %s", buf);
-       tts_speak(buf, EINA_TRUE);
+       tw_speak(buf, EINA_TRUE);
 }
 
 static void timer_reschedule(App_Tracker_Data *atd)
@@ -348,7 +348,7 @@ static void _on_atspi_event_cb(AtspiEvent *event, void *user_data)
                                        text_to_speak = reading_composer_description_get(rc);
                                        reading_composer_data_free(rc);
                                        DEBUG("SPEAK : %s", text_to_speak ? text_to_speak : "text_to_speak nil");
-                                       tts_speak_customized(text_to_speak, EINA_TRUE, EINA_TRUE, event->source, 0);
+                                       tw_speak_customized(text_to_speak, EINA_TRUE, EINA_TRUE, event->source, 0);
                                        free(text_to_speak);
                                }
                                else {
@@ -403,9 +403,9 @@ static void _on_atspi_event_cb(AtspiEvent *event, void *user_data)
                else if ((role == ATSPI_ROLE_WINDOW) && (event->source == atd->root)) {
                        if (rect) {
                                if (rect->width > rect->height)
-                                       SUPPRESS_FORMAT_ERROR(tts_speak(_IGNORE_ON_TV("IDS_ACCS_OPT_LANDSCAPE_VIEW_TTS"), EINA_TRUE));
+                                       SUPPRESS_FORMAT_ERROR(tw_speak(_IGNORE_ON_TV("IDS_ACCS_OPT_LANDSCAPE_VIEW_TTS"), EINA_TRUE));
                                else
-                                       SUPPRESS_FORMAT_ERROR(tts_speak(_IGNORE_ON_TV("IDS_ACCS_OPT_PORTRAIT_VIEW_TTS"), EINA_TRUE));
+                                       SUPPRESS_FORMAT_ERROR(tw_speak(_IGNORE_ON_TV("IDS_ACCS_OPT_PORTRAIT_VIEW_TTS"), EINA_TRUE));
                                DEBUG("Window geometry: %d %d", rect->width, rect->height);
                        }
                }
@@ -418,7 +418,7 @@ static void _on_atspi_event_cb(AtspiEvent *event, void *user_data)
                        return;
                }
                DEBUG("New name for object, read:%s", name);
-               tts_speak_customized(name, EINA_TRUE, EINA_TRUE, event->source, 0);
+               tw_speak_customized(name, EINA_TRUE, EINA_TRUE, event->source, 0);
                g_free(name);
                return;
        }
@@ -434,7 +434,7 @@ static void _on_atspi_event_cb(AtspiEvent *event, void *user_data)
                                ERROR("name is null");
                                return;
                        }
-                       tts_speak_customized(name, EINA_TRUE, EINA_TRUE, event->source, 0);
+                       tw_speak_customized(name, EINA_TRUE, EINA_TRUE, event->source, 0);
                        g_free(name);
                }
        } else if (!g_strcmp0(event->type, "object:state-changed:animated") && (role == ATSPI_ROLE_LIST_ITEM)
@@ -446,7 +446,7 @@ static void _on_atspi_event_cb(AtspiEvent *event, void *user_data)
                        SUPPRESS_FORMAT_ERROR(g_snprintf(buf, sizeof(buf), _IGNORE_ON_TV("IDS_COM_POP_STARTED_DRAGGING_ITEM_AT_POSITION_PD_TTS"), idx + 1));
                else
                        SUPPRESS_FORMAT_ERROR(g_snprintf(buf, sizeof(buf), _("IDS_COM_POP_ITEM_DROPPED_INTO_POSITION_PD_TTS"), idx + 1));
-               tts_speak_customized(buf, EINA_TRUE, EINA_TRUE, event->source, 0);
+               tw_speak_customized(buf, EINA_TRUE, EINA_TRUE, event->source, 0);
                g_error_free(err);
        }
 
@@ -470,7 +470,7 @@ static void _on_atspi_event_cb(AtspiEvent *event, void *user_data)
                        else
                                g_strlcat(buf, _("IDS_ACCS_OPT_NOT_SELECTED_TTS"), sizeof(buf) - strlen(buf) - 1);
                }
-               tts_speak(buf, EINA_TRUE);
+               tw_speak(buf, EINA_TRUE);
                g_free(name);
        } else if (!g_strcmp0(event->type, "object:state-changed:selected")
                           && (get_objects_attributes(event->source) & ACCESSIBLE_READING_INFO_TYPE_STATE)) {
@@ -494,7 +494,7 @@ static void _on_atspi_event_cb(AtspiEvent *event, void *user_data)
                                g_strlcat(buf, _("IDS_ACCS_BODY_SELECTED_TTS"), sizeof(buf) - strlen(buf) - 1);
                        else
                                g_strlcat(buf, _IGNORE_ON_TV("IDS_ACCS_BODY_DOUBLE_TAP_TO_SELECT_TTS"), sizeof(buf) - strlen(buf) - 1);
-                       tts_speak(buf, EINA_TRUE);
+                       tw_speak(buf, EINA_TRUE);
                } else if (role == ATSPI_ROLE_LIST_ITEM && atspi_accessible_get_role(parent, NULL) == ATSPI_ROLE_TREE_TABLE) {
                        if (event->detail1) {
                                AtspiStateSet *parent_state_set = atspi_accessible_get_state_set(parent);
@@ -516,7 +516,7 @@ static void _on_atspi_event_cb(AtspiEvent *event, void *user_data)
                                } else {
                                        g_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s", _("IDS_ACCS_BODY_SELECTED_TTS"));
                                }
-                               tts_speak(buf, EINA_TRUE);
+                               tw_speak(buf, EINA_TRUE);
                                g_object_unref(parent_state_set);
                        }
                }
@@ -565,7 +565,7 @@ static void _on_atspi_event_cb(AtspiEvent *event, void *user_data)
 
                        DEBUG("speaking mode is %d", mode);
                        if (mode != 0)
-                               tts_speak(buf, mode == 1);
+                               tw_speak(buf, mode == 1);
 
                        return;
                }
@@ -607,7 +607,7 @@ static void _on_atspi_event_cb(AtspiEvent *event, void *user_data)
                                        }
                                }
                                DEBUG("Text deleted :%s", buf);
-                               tts_speak(buf, EINA_TRUE);
+                               tw_speak(buf, EINA_TRUE);
                        }
                } else if (role == ATSPI_ROLE_PASSWORD_TEXT) {
                        if ((!g_strcmp0(event->type, "object:text-changed:insert") || !g_strcmp0(event->type, "object:text-changed:delete"))) {
@@ -623,7 +623,7 @@ static void _on_atspi_event_cb(AtspiEvent *event, void *user_data)
                                                                                                   count));
                                        g_object_unref(iface_text);
                                }
-                               tts_speak(buf, EINA_TRUE);
+                               tw_speak(buf, EINA_TRUE);
                        }
                }
        }
index 874f5c76d02e260b784570e45e321a8e08f30a3b..a9ac264d399206fb9f7af66f4bd5c2e6a1cdb349 100644 (file)
@@ -60,7 +60,7 @@ _consume_pause_resume_command(const Eldbus_Service_Interface *iface EINA_UNUSED,
                if (!eldbus_message_arguments_get(msg, "b", &pause_resume)) {
                        ERROR("eldbus_message_arguments_get() failed to parse arguments of type Boolean from message msg=%p", msg);
                } else {
-                       tts_pause_set(pause_resume);
+                       tw_pause_set(pause_resume);
                }
        } else {
                ERROR("eldbus_message_method_return_new(%p) has failed to create a reply message", msg);
@@ -81,7 +81,7 @@ _consume_stop_command(const Eldbus_Service_Interface *iface EINA_UNUSED, const E
                if (reply) eldbus_message_unref(reply);
                reply =  eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "failed to parse arguments");
        } else if (reply) {
-               tts_purge(!non_discardable_also);
+               tw_purge(!non_discardable_also);
        } else {
                ERROR("eldbus_message_method_return_new(%p) has failed to create a reply message", msg);
        }
@@ -105,7 +105,7 @@ _consume_read_command(const Eldbus_Service_Interface *iface EINA_UNUSED, const E
                reply =  eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "failed to parse arguments");
        } else if (reply) {
                DEBUG("RECIVED DBUS MESSAGE WITH ARGS: text(%s), discardable(%d)", text, discardable);
-               Read_Command *command = tts_speak_customized(text, EINA_TRUE, discardable, NULL, 0);
+               Read_Command *command = tw_speak_customized(text, EINA_TRUE, discardable, NULL, 0);
                if (command) rc_id = command->command_id;
                if (!eldbus_message_arguments_append(reply, "sbi", text, discardable, rc_id))
                        ERROR("eldbus_message_arguments_append() has failed to append arguments to reply message reply=%p", reply);
index 99d63a0e981c3c2f840c484a8417c9d4a81ef2ff..466949383e3371d6de2f45aaa3caa67c8800c5d3 100644 (file)
@@ -196,7 +196,7 @@ void granularity_read_type_set(Eina_Bool next)
        gchar text[30] = "";
        g_snprintf(text, sizeof(text) - strlen(text), "%s granularity", granularity_read_type_text[grd->granularity_read_type]); /* TODO : UX dependent*/
        DEBUG("SPEAK : %s", text);
-       tts_speak(text, EINA_TRUE);
+       tw_speak(text, EINA_TRUE);
 
        if (grd->current_text) {
                if (grd->text_list) {
index 7168d67e3a365fa6cd11ea10c067adb82fb282b9..e016627de5e9889a5e49ff442612afff49f77f2c 100644 (file)
@@ -58,14 +58,14 @@ static gboolean async_keyboard_cb(const AtspiDeviceEvent *stroke, void *data)
 {
        DEBUG("AT-SPI DEVICE EVENT: ID(%d) STRING(%s) TYPE(%d) HW_CODE(%d) MODIFIERS(%d) TIMESTAMP(%d)", stroke->id, stroke->event_string, stroke->type, stroke->hw_code, stroke->modifiers, stroke->timestamp);
        if (!g_strcmp0(stroke->event_string, "XF86Back")) {
-               tts_speak(_("MIDS_MH_BODY_BACK_BUTTON_T_TTS"), EINA_TRUE);
+               tw_speak(_("MIDS_MH_BODY_BACK_BUTTON_T_TTS"), EINA_TRUE);
                return TRUE;
        } else if (!g_strcmp0(stroke->event_string, "XF86PowerOff")) {
-               tts_purge(EINA_FALSE);
+               tw_purge(EINA_FALSE);
                return TRUE;
        } else if (!g_strcmp0(stroke->event_string, "XF86AudioPause")) {
-               Eina_Bool paused = tts_pause_get();
-               tts_pause_set(!paused);
+               Eina_Bool paused = tw_pause_get();
+               tw_pause_set(!paused);
                return TRUE;
        } else
                return FALSE;
@@ -84,12 +84,12 @@ static void keyboard_changed_cb(keynode_t *node, void *user_data)
 
        if (keyboard_state == ktd->prev_keyboard_state) return;
        if (keyboard_state == VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW) {
-               tts_speak(_("IDS_IME_BODY_KEYBOARD_DISPLAYED_T_TTS"), EINA_FALSE);
-               DEBUG("tts_speak Keyboard shown\n");
+               tw_speak(_("IDS_IME_BODY_KEYBOARD_DISPLAYED_T_TTS"), EINA_FALSE);
+               DEBUG("tw_speak Keyboard shown\n");
                ktd->prev_keyboard_state = keyboard_state;
        } else if (keyboard_state == VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE) {
-               tts_speak(_("IDS_ACCS_BODY_KEYBOARD_HIDDEN_TTS"), EINA_FALSE);
-               DEBUG("tts_speak keyboard hidden\n");
+               tw_speak(_("IDS_ACCS_BODY_KEYBOARD_HIDDEN_TTS"), EINA_FALSE);
+               DEBUG("tw_speak keyboard hidden\n");
                ktd->prev_keyboard_state = keyboard_state;
        }
 }
index 722eb1b4bedb3050f449b2129cbe800e51e1172a..2c5bee0f62cfbd3e708241546f159766ea8943f0 100644 (file)
@@ -280,7 +280,7 @@ static int app_reset(bundle *b,  void *user_data)
                char buf[255] = "";
                g_snprintf(buf, sizeof(buf), "%s %s",
                                 _("IDS_ST_MBODY_SCREEN_READER_HTTS"), _("IDS_MSG_BODY_ON_T_TTS"));
-               tts_speak_customized(buf, EINA_TRUE, EINA_FALSE, NULL, 0);
+               tw_speak_customized(buf, EINA_TRUE, EINA_FALSE, NULL, 0);
 #endif
        }
 
index c1490a30626196557cf4725254b26c9f90ae5dec..4d81912d69345dd0c80eec8eb174b02ef50a1b72 100644 (file)
@@ -336,9 +336,9 @@ void generate_what_to_read_and_speak(Navigator_Data *nd, AtspiAccessible *obj, E
 
        DEBUG("reading %s", tmp1);
        DEBUG("reading description %s", tmp2);
-       tts_speak_customized(tmp1, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
+       tw_speak_customized(tmp1, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
        if (tmp2 && tmp2[0])
-               tts_speak_customized(tmp2, EINA_FALSE, EINA_TRUE, associate_object ? obj : NULL, DESCRIPTION_SPEAK_DELAY);
+               tw_speak_customized(tmp2, EINA_FALSE, EINA_TRUE, associate_object ? obj : NULL, DESCRIPTION_SPEAK_DELAY);
        g_free(tmp1);
        g_free(tmp2);
 }
@@ -482,10 +482,10 @@ static void _current_highlight_object_set(Navigator_Data *nd, AtspiAccessible *
                }
                GERROR_CHECK(err)
 
-               Eina_Bool is_paused = tts_pause_get();
+               Eina_Bool is_paused = tw_pause_get();
                if (is_paused) {
-                       tts_stop_set();
-                       tts_pause_set(EINA_FALSE);
+                       tw_stop_set();
+                       tw_pause_set(EINA_FALSE);
                }
        } else
                DEBUG("Unable to highlight on object");
@@ -750,9 +750,9 @@ static void _caret_move_beg(Navigator_Data *nd)
                        DEBUG("Caret position increment done");
                        gchar *text = atspi_text_get_text(text_interface, 0, 1, NULL);
                        DEBUG("SPEAK : %s", text ? text : "text nil");
-                       tts_speak_customized(text, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
+                       tw_speak_customized(text, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
                        //FIXME : This IDS value is not supported.
-                       //tts_speak_customized(_("IDS_TEXT_BEGIN"), EINA_FALSE, EINA_TRUE, nd->current_obj);
+                       //tw_speak_customized(_("IDS_TEXT_BEGIN"), EINA_FALSE, EINA_TRUE, nd->current_obj);
                        g_free(text);
                } else {
                        ERROR("Caret position increment error");
@@ -784,7 +784,7 @@ static void _caret_move_end(Navigator_Data *nd)
                        //FIXME : This IDS value is not supported.
                        /*DEBUG("Caret position increment done");
                        DEBUG("SPEAK:%s", _("IDS_TEXT_END"));
-                       tts_speak_customized(_("IDS_TEXT_END"), EINA_TRUE, EINA_TRUE, nd->current_obj);*/
+                       tw_speak_customized(_("IDS_TEXT_END"), EINA_TRUE, EINA_TRUE, nd->current_obj);*/
                } else
                        ERROR("Caret position to end error");
                g_clear_error(&err);
@@ -830,7 +830,7 @@ static void _cut_or_copy_selected_text(Navigator_Data *nd, Eina_Bool is_cut)
                                                //TODO: i18n - copy, cut
                                                char buf[TTS_MAX_TEXT_SIZE] = "";
                                                g_snprintf(buf, sizeof(buf), (is_cut) ? _("Cut , %s") : _("Copy , %s"), text);
-                                               tts_speak_customized(buf, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
+                                               tw_speak_customized(buf, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
                                        }
                                        g_free(text);
                                        g_object_unref(e_text);
@@ -902,7 +902,7 @@ static void _paste_text(Navigator_Data *nd)
                                        //TODO: i18n - paste
                                        char buf[TTS_MAX_TEXT_SIZE] = "";
                                        g_snprintf(buf, sizeof(buf), _("Paste , %s"), text);
-                                       tts_speak_customized(buf, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
+                                       tw_speak_customized(buf, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
                                        g_free(text);
                                }
                                g_object_unref(e_text);
@@ -944,7 +944,7 @@ static void _select_all_text(Navigator_Data *nd)
                                //TODO : i18n - "From %s to %s, selected", "All selected"
                                char buf[TTS_MAX_TEXT_SIZE] = "";
                                g_snprintf(buf, sizeof(buf), _("All selected , %s"), text);
-                               tts_speak_customized(buf, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
+                               tw_speak_customized(buf, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
                                g_free(text);
                        }
                }
@@ -1041,7 +1041,7 @@ static void _select_text_forward(Navigator_Data *nd, Eina_Bool forward)
 
                                        char buf[TTS_MAX_TEXT_SIZE] = "";
                                        g_snprintf(buf, sizeof(buf), (is_selected) ? _("%s , Selected") : _("%s , Unselected"), text);
-                                       tts_speak_customized(buf, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
+                                       tw_speak_customized(buf, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
                                        g_free(text);
                                }
                                ret = atspi_text_set_caret_offset(text_interface, current_offset, &err);
@@ -1091,15 +1091,15 @@ static void _caret_move_forward(Navigator_Data *nd)
                        if (offset_pos == atspi_text_get_character_count(text_interface, NULL)) {
                                //FIXME : This IDS value is not supported.
                                /*DEBUG("SPEAK:%s", _("IDS_TEXT_END"));
-                               tts_speak_customized(_("IDS_TEXT_END"), EINA_FALSE, EINA_TRUE, current_obj);*/
+                               tw_speak_customized(_("IDS_TEXT_END"), EINA_FALSE, EINA_TRUE, current_obj);*/
                        } else {
                                DEBUG("SPEAK:%s", text ? text : "text nil");
                                const gchar *symtext = symbol_lookup(text);
                                if (symtext) {
-                                       tts_speak_customized(_(symtext), EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
+                                       tw_speak_customized(_(symtext), EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
                                }
                                else {
-                                       tts_speak_customized(text, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
+                                       tw_speak_customized(text, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
                                }
                        }
                        g_free(text);
@@ -1145,16 +1145,16 @@ static void _caret_move_backward(Navigator_Data *nd)
                        DEBUG("SPEAK:%s", text ? text : "text nil");
                        const gchar *symtext = symbol_lookup(text);
                        if (symtext) {
-                               tts_speak_customized(_(symtext), EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
+                               tw_speak_customized(_(symtext), EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
                        }
                        else {
-                               tts_speak_customized(text, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
+                               tw_speak_customized(text, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
                        }
                        g_free(text);
                        //FIXME : This IDS value is not supported.
                        /*if (offset_pos == 0) {
                                DEBUG("SPEAK:%s", _("IDS_TEXT_BEGIN"));
-                               tts_speak_customized(_("IDS_TEXT_BEGIN"), EINA_FALSE, EINA_TRUE, nd->current_obj);
+                               tw_speak_customized(_("IDS_TEXT_BEGIN"), EINA_FALSE, EINA_TRUE, nd->current_obj);
                        }*/
                } else {
                        ERROR("Caret position decrement error");
@@ -1522,8 +1522,8 @@ static void _set_pause(void)
        DEBUG("START");
 
        Eina_Bool res = EINA_FALSE;
-       bool pause = tts_pause_get();
-       res = tts_pause_set(!pause);
+       bool pause = tw_pause_get();
+       res = tw_pause_set(!pause);
        if (!res)
                ERROR("Failed to set pause state");
 
@@ -1986,7 +1986,7 @@ static Eina_Bool _granularity_text_read(Navigator_Data *nd, Eina_Bool next)
        if (grd) {
                char *granularity_text_to_speak = granularity_read_text_get(nd->current_obj, next);
                if (granularity_text_to_speak) {
-                       tts_speak_customized(granularity_text_to_speak, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
+                       tw_speak_customized(granularity_text_to_speak, EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
                        g_free(granularity_text_to_speak);
                }
                return EINA_TRUE;
@@ -2363,11 +2363,11 @@ static void on_gesture_detected(void *data, const Eldbus_Message *msg)
                        _wm_text_selection_mode_set(nd, !nd->is_text_selection_mode);
                        if (nd->is_text_selection_mode) {
                                //TODO: i18n - "Selection mode enabled".
-                               tts_speak_customized(_("Selection mode enabled"),
+                               tw_speak_customized(_("Selection mode enabled"),
                                                                         EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
                        } else {
                                //TODO: i18n - "Selection mode disabled".
-                               tts_speak_customized(_("Selection mode disabled"),
+                               tw_speak_customized(_("Selection mode disabled"),
                                                                         EINA_TRUE, EINA_TRUE, nd->current_obj, 0);
                        }
                } else
@@ -2592,7 +2592,7 @@ Navigator_Data *navigator_init(void)
        nd->read_quickpanel_cb = NULL;
        nd->read_quickpanel_data = NULL;
 
-       set_utterance_cb(_on_utterance, nd);
+       tw_set_utterance_cb(_on_utterance, nd, NULL);
 
        navigator_gestures_tracker_register(on_gesture_detected, nd);
        // register on active_window
@@ -2636,7 +2636,7 @@ void navigator_shutdown(Navigator_Data *nd)
        nd->supported_gestures = NULL;
 
        navigator_gestures_tracker_unregister();
-       remove_utterance_cb();
+       tw_set_utterance_cb(NULL, NULL, NULL);
 
        app_tracker_shutdown(nd->app_tracker_data);
        smart_notification_shutdown();
index d060ba29d8ef68cbb7cf46690a24b5e1722815e9..4eb9590628e777f5a8574d094d8762a8b3e7710b 100644 (file)
@@ -39,11 +39,6 @@ Service_Data service_data = {
 
        //Set by vconf
        .run_service = 1,
-
-       //Set by tts
-       .tts = NULL,
-       .available_languages = NULL,
-       .text_to_say_info = NULL,
 };
 
 Service_Data *get_pointer_to_service_data_struct()
@@ -54,7 +49,7 @@ Service_Data *get_pointer_to_service_data_struct()
 int screen_reader_create_service(Service_Data *service_data)
 {
        vc_init();
-       tts_init(service_data);
+       tw_init();
 
 #ifdef SCREEN_READER_TV
        service_data->spi_data = spi_init();
@@ -72,8 +67,7 @@ int screen_reader_terminate_service(Service_Data *service_data)
 #endif
        vc_exit();
 
-       tts_destroy(service_data->tts);
-       service_data->current_value = NULL;
+       tw_shutdown();
        return 0;
 }
 
index 895f57800ecaab83d2586800fe26d0cc27a214da..1526188964f5c186eaa577df81a7943abf031aef 100644 (file)
@@ -311,9 +311,9 @@ static Eina_Bool _signal_handling_timer_cb(void *data)
 
        DEBUG("Read text = %s (source: %p)\n", shtd->text_to_read, shtd->obj);
        shtd->inside_cb = EINA_TRUE;
-       tts_speak_customized(shtd->text_to_read, shtd->want_discard_previous_reading, shtd->discardable, shtd->obj, 0);
+       tw_speak_customized(shtd->text_to_read, shtd->want_discard_previous_reading, shtd->discardable, shtd->obj, 0);
        if (shtd->desc_to_read)
-               tts_speak_customized(shtd->desc_to_read, shtd->want_discard_previous_reading, shtd->discardable, shtd->obj, DESCRIPTION_SPEAK_DELAY);
+               tw_speak_customized(shtd->desc_to_read, shtd->want_discard_previous_reading, shtd->discardable, shtd->obj, DESCRIPTION_SPEAK_DELAY);
 
        free_shtd(shtd);
 
@@ -365,7 +365,7 @@ void spi_event_listener_cb(AtspiEvent *event, void *user_data)
        shtd->discardable = EINA_TRUE;
        if (cancel) {
                shtd->want_discard_previous_reading = EINA_TRUE;
-               tts_purge(EINA_TRUE);
+               tw_purge(EINA_TRUE);
                DEBUG("Reading cancelled, tts purged");
                if (spi->signal_handling_timer) {
                        DEBUG("Reading cancelled, timer deleted");
index 44b7114328b4041e029687b06fb3aa4d6eb3d249..9def0067d737147eba8bdf12c2275aca2fc9a263 100644 (file)
@@ -30,9 +30,9 @@
 #include <notification.h>
 #include <notification_list.h>
 
+#include <logger.h>
 #include <screen_reader_system.h>
-#include "screen_reader_tts.h"
-#include "logger.h"
+#include <screen_reader_tts.h>
 
 #define MAX_SIM_COUNT 2
 #define DATE_TIME_BUFFER_SIZE 26
@@ -173,11 +173,11 @@ static void device_system_cb(device_callback_e type, void *value, void *user_dat
                }
 
                if (status == DEVICE_BATTERY_LEVEL_LOW)
-                       tts_speak(_IGNORE_ON_TV("IDS_ST_MBODY_LOW_BATTERY"), EINA_TRUE);
+                       tw_speak(_IGNORE_ON_TV("IDS_ST_MBODY_LOW_BATTERY"), EINA_TRUE);
                else if (status == DEVICE_BATTERY_LEVEL_CRITICAL)
-                       tts_speak(_IGNORE_ON_TV("IDS_COM_HEADER_BATTERY_CRITICALLY_LOW"), EINA_TRUE);
+                       tw_speak(_IGNORE_ON_TV("IDS_COM_HEADER_BATTERY_CRITICALLY_LOW"), EINA_TRUE);
                else if (status == DEVICE_BATTERY_LEVEL_FULL)
-                       tts_speak(_IGNORE_ON_TV("IDS_QP_MBODY_BATTERY_FULLY_CHARGED_ABB"), EINA_TRUE);
+                       tw_speak(_IGNORE_ON_TV("IDS_QP_MBODY_BATTERY_FULLY_CHARGED_ABB"), EINA_TRUE);
        } else if (type == DEVICE_CALLBACK_DISPLAY_STATE) {
                display_state_e state;
 
@@ -193,7 +193,7 @@ static void device_system_cb(device_callback_e type, void *value, void *user_dat
                                while turning off display affects or not. If it has a problem we need to use
                                following is_screen_turn_off, and above system_data->is_display_state_screen_off */
                                Read_Command *rc = NULL;
-                               rc = tts_speak(_("IDS_GCTS_OPT_SCREEN_TURNED_OFF_TTS"), EINA_FALSE);
+                               rc = tw_speak(_("IDS_GCTS_OPT_SCREEN_TURNED_OFF_TTS"), EINA_FALSE);
                                if (rc) rc->is_screen_turn_off = EINA_TRUE;
                        }
                } else {
@@ -246,7 +246,7 @@ static void device_time_get(System_Data *system_data)
                strftime(buffer, DATE_TIME_BUFFER_SIZE, "Current time: %I %M %p", timeinfo);
 
        DEBUG("Text to say: %s", buffer);
-       tts_speak(buffer, EINA_FALSE);
+       tw_speak(buffer, EINA_FALSE);
 }
 
 char *device_error_to_string(int e)
@@ -344,7 +344,7 @@ static void device_battery_get(System_Data *system_data)
        }
 
        DEBUG("Text to say: %s", buffer);
-       tts_speak(buffer, EINA_FALSE);
+       tw_speak(buffer, EINA_FALSE);
        g_free(buffer);
 }
 
@@ -422,7 +422,7 @@ static void _signal_strength_sim_get(System_Data *system_data)
        buffer = eina_strbuf_string_steal(str_buf);
 
        DEBUG("Text to say: %s", buffer);
-       tts_speak(buffer, EINA_FALSE);
+       tw_speak(buffer, EINA_FALSE);
 
        eina_strbuf_free(str_buf);
        g_free(buffer);
@@ -468,7 +468,7 @@ static void _signal_strength_wifi_get(System_Data *system_data)
                                return;
                        }
 
-                       tts_speak(buffer, EINA_FALSE);
+                       tw_speak(buffer, EINA_FALSE);
                        g_free(buffer);
                        return;
                }
@@ -500,7 +500,7 @@ static void _signal_strength_wifi_get(System_Data *system_data)
                }
 
                DEBUG("Text to say: %s", buffer);
-               tts_speak(buffer, EINA_FALSE);
+               tw_speak(buffer, EINA_FALSE);
                g_free(buffer);
                wifi_manager_ap_destroy(ap);
        }
@@ -556,15 +556,15 @@ static void device_missed_events_get(System_Data *system_data)
        }
 
        if (noti_count == 0) {
-               tts_speak(_("IDS_GCTS_OPT_NO_EVENTS_TTS"), EINA_FALSE);
+               tw_speak(_("IDS_GCTS_OPT_NO_EVENTS_TTS"), EINA_FALSE);
        } else if (noti_count == 1) {
-               tts_speak(_IGNORE_ON_TV("IDS_SCR_BODY_1_UNREAD_ITEM"), EINA_FALSE);
+               tw_speak(_IGNORE_ON_TV("IDS_SCR_BODY_1_UNREAD_ITEM"), EINA_FALSE);
        } else {
                SUPPRESS_FORMAT_ERROR(ret = asprintf(&buffer, _IGNORE_ON_TV("IDS_SCR_BODY_PD_UNREAD_ITEMS"), noti_count));
                if (ret < 0)
                        ERROR("buffer allocation error");
 
-               tts_speak(buffer, EINA_FALSE);
+               tw_speak(buffer, EINA_FALSE);
                g_free(buffer);
        }
 
@@ -616,7 +616,7 @@ static void device_date_get(System_Data *system_data)
        }
 
        DEBUG("Text to say: %s", buffer);
-       tts_speak(buffer, EINA_FALSE);
+       tw_speak(buffer, EINA_FALSE);
 }
 
 static bool bonded_device_count_cb(bt_device_info_s *device_info, void *user_data)
@@ -657,7 +657,7 @@ static void device_bluetooth_get(System_Data *system_data)
                char buf[255];
                g_snprintf(buf, sizeof(buf), "%s %s", _("IDS_BT_BODY_BLUETOOTH"), _("IDS_ALM_BODY_OFF"));
                DEBUG("Text to say: %s", buf);
-               tts_speak(buf, EINA_FALSE);
+               tw_speak(buf, EINA_FALSE);
                return;
        } else {
                bt_adapter_foreach_bonded_device(bonded_device_count_cb, (void *)&device_count);
@@ -677,7 +677,7 @@ static void device_bluetooth_get(System_Data *system_data)
                }
 
                DEBUG("Text to say: %s", buffer);
-               tts_speak(buffer, EINA_FALSE);
+               tw_speak(buffer, EINA_FALSE);
                g_free(buffer);
        }
 }
index fb170cb2b726465e9bea0c57bfa1291ca0669cd3..68d2e41cf1069bfb905165cbb68b6fb526a2c7ea 100644 (file)
 
 #include <Ecore.h>
 #include <atspi/atspi.h>
-#include "screen_reader_tts.h"
-#include "screen_reader_vconf.h"
-#include "screen_reader_system.h"
-#include "dbus_direct_reading_adapter.h"
-#include "logger.h"
-#include "utils.h"
 
-// ---------------------------- DEBUG HELPERS ------------------------------
+#include <dbus_direct_reading_adapter.h>
+#include <logger.h>
+#include <screen_reader_system.h>
+#include <screen_reader_tts.h>
+#include <screen_reader_vconf.h>
+#include <utils.h>
 
 #define REMOVE_PRECEDING_READ_COMMANDS_LIMIT 1
 
+typedef enum _Play_Read_Command_Status Play_Read_Command_Status;
+
+typedef struct {
+       int init;
+       tts_h tts;
 #ifndef SCREEN_READER_TV
-Ecore_Timer *display_lock_release_timer = NULL;
+       Ecore_Timer *display_lock_release_timer;
 #endif
+       Eina_Bool pause_state;
+       Eina_List *read_command_queue;
+
+       // Current read command - the last accepted by the TTS and not yet completed.
+       Read_Command *last_read_command;
+
+       // Callback type
+       utterance_cb_t on_utterance_end;
+       void* on_utterance_end_user_data;
+       utterance_cb_t on_utterance_end_deleter;
+
+       Eina_Bool tts_speak_running;
+       int tts_speak_last_utterance;
+
+       Ecore_Timer *delay_timer;
+       bool request_speak_do;
+       bool running;
+} TWData;
+
+/* Forward delcarations - begin */
+static TWData *tw_get_instance(void);
+static void tw_speak_request(TWData *tw);
+static void overwrite_last_read_command_with(TWData *tw, Read_Command *new_value);
+static void _reading_status_notify(Signal signal, Read_Command *command);
+static void dispose_read_command(Read_Command *command, Signal playing_reason, Signal non_playing_reason);
+/* Forward delcarations - end */
 
-static Eina_Bool pause_state = EINA_FALSE;
-static Eina_List *read_command_queue = NULL;
-
-// Current read command - the last accepted by the TTS and not yet completed.
-static Read_Command *last_read_command = NULL;
-
-// Callback type
-typedef void (*utterance_completed_f)(void*);
-static utterance_completed_f on_utterance_end;
-static void* on_utterance_end_user_data;
-
-const char *sprintf_command(Read_Command *command)
+static const char *sprintf_command(Read_Command *command)
 {
        static char buffer[9999];
        if (command) {
@@ -119,19 +138,41 @@ static const char *get_tts_state(tts_state_e r)
 }
 
 //-------------------------------------------------------------------------------------------------
-void state_changed_cb(tts_h tts, tts_state_e previous, tts_state_e current, void *user_data);
+static void tw_state_changed_cb(
+               tts_h tts,
+               tts_state_e previous,
+               tts_state_e current,
+               void *user_data)
+{
+       TWData *tw = (TWData*) user_data;
+       if (tw->pause_state) {
+               DEBUG("TTS is currently paused. Resume to start reading");
+               return;
+       }
 
-void set_utterance_cb(utterance_completed_f uter_cb, void *user_data)
-{
-       on_utterance_end = uter_cb;
-       on_utterance_end_user_data = user_data;
+       DEBUG("++++++++++++++++tw_state_changed_cb++++++++++++++++++");
+       DEBUG("current state:%s and previous state:%s\n", get_tts_state(current), get_tts_state(previous));
+       if (current == TTS_STATE_READY && previous == TTS_STATE_PLAYING
+                       && tw->last_read_command && tw->last_read_command->is_playing) {
+               overwrite_last_read_command_with(tw, NULL);
+       }
+
+       if (TTS_STATE_READY == current)
+               tw_speak_request(tw);
 }
 
-void* remove_utterance_cb() {
-       void *ret = on_utterance_end_user_data;
-       on_utterance_end = NULL;
-       on_utterance_end_user_data = NULL;
-       return ret;
+void tw_set_utterance_cb(
+               utterance_cb_t uter_cb,
+               void *user_data,
+               utterance_cb_t deleter)
+{
+       TWData *tw = tw_get_instance();
+       if (tw->on_utterance_end_user_data && tw->on_utterance_end_deleter)
+               tw->on_utterance_end_deleter(tw->on_utterance_end_user_data);
+
+       tw->on_utterance_end = uter_cb;
+       tw->on_utterance_end_user_data = user_data;
+       tw->on_utterance_end_deleter = deleter;
 }
 
 static Eina_Bool _do_atspi_action_by_name(AtspiAccessible *obj, const char *name)
@@ -198,17 +239,16 @@ static void dispose_read_command(Read_Command *command, Signal playing_reason, S
        }
 }
 
-static void overwrite_last_read_command_with(Read_Command *new_value)
+static void overwrite_last_read_command_with(TWData *tw, Read_Command *new_value)
 {
-       Read_Command *old_head = last_read_command;
-       last_read_command = new_value;
+       Read_Command *old_head = tw->last_read_command;
+       tw->last_read_command = new_value;
        DEBUG("Replacing head: %s", sprintf_command(old_head));
        if (old_head)
                dispose_read_command(old_head, READING_CANCELLED, READING_STOPPED);
 }
 
-Eina_Bool
-can_discard(const Read_Command *prev, const Read_Command *next)
+static Eina_Bool can_discard(const Read_Command *prev, const Read_Command *next)
 {
        DEBUG("[START] checking if can discard: prev (%p), next(%p)", prev, next);
        char buffer[64];
@@ -219,26 +259,23 @@ can_discard(const Read_Command *prev, const Read_Command *next)
        return next == NULL ? EINA_FALSE : (prev == NULL ? EINA_TRUE : (prev->discardable && next->want_discard_previous_reading));
 }
 
-Eina_Bool can_be_discarded(const Read_Command *prev)
+static Eina_Bool can_be_discarded(TWData *tw, const Read_Command *prev)
 {
        Eina_List *l;
        Read_Command *command;
 
-       EINA_LIST_FOREACH(read_command_queue, l, command) {
+       EINA_LIST_FOREACH(tw->read_command_queue, l, command) {
                if (can_discard(prev, command))
                        return EINA_TRUE;
        }
        return can_discard(prev, NULL);
 }
 
-static void  _reading_status_notify(Signal signal, Read_Command *command);
-static void dispose_read_command(Read_Command *command, Signal playing_reason, Signal non_playing_reason);
-
 // Retrieves first non-discardable command from the queue (if there is one)
 // or the last command in the queue (if all are discardable).
 //
 //TODO: consider handling the case of discarding well-formed read command by subsequent malformed command
-static Read_Command *get_read_command_from_queue(Eina_List **cmd_list)
+static Read_Command *get_read_command_from_queue(TWData *tw, Eina_List **cmd_list)
 {
        if (cmd_list == NULL || *cmd_list == NULL)
                return NULL;
@@ -251,7 +288,7 @@ static Read_Command *get_read_command_from_queue(Eina_List **cmd_list)
                *cmd_list = eina_list_remove(*cmd_list, result);
 
                // command is not discardable
-               if (!can_be_discarded(result) && (result->context.text != NULL))
+               if (!can_be_discarded(tw, result) && (result->context.text != NULL))
                        break;
 
                // next command have delay_to_speak
@@ -284,7 +321,6 @@ enum _Play_Read_Command_Status {
        FAILURE_NOT_RECOVERABLE = 2
 };
 
-typedef enum _Play_Read_Command_Status Play_Read_Command_Status;
 
 static bool is_separator(int unicode)
 {
@@ -383,19 +419,16 @@ static int extract_utf8_chunk(char **utf8_line, const char *txt, int limit)
        return 0;
 }
 
-static volatile Eina_Bool tts_speak_running = false;
-static volatile int tts_speak_last_utterance = -1;
-
-static int send_chunk_to_tts(Service_Data *sd, const char *utf8_line, int *utt_id)
+static int send_chunk_to_tts(TWData *tw, const char *utf8_line, int *utt_id)
 {
        DEBUG("Passing TEXT: %s to TTS", utf8_line);
        int utterance_id;
-       int ret = tts_add_text(sd->tts, utf8_line, NULL, TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &utterance_id);
+       int ret = tts_add_text(tw->tts, utf8_line, NULL, TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &utterance_id);
        if (ret) {
                tts_state_e state = -1;
                switch (ret) {
                case TTS_ERROR_INVALID_STATE:
-                       tts_get_state(sd->tts, &state);
+                       tts_get_state(tw->tts, &state);
                        dlog_print(DLOG_FATAL, NULL, "FAILED tts_add_text: error: TTS_ERROR_INVALID_STATE, tts_state: %d", state);
                        return FAILURE_RECOVERABLE;
                case TTS_ERROR_INVALID_VOICE:
@@ -416,19 +449,19 @@ static int send_chunk_to_tts(Service_Data *sd, const char *utf8_line, int *utt_i
                        return FAILURE_NOT_RECOVERABLE;
                }
        } else {
-               tts_speak_running = EINA_TRUE;
-               tts_speak_last_utterance = utterance_id;
+               tw->tts_speak_running = EINA_TRUE;
+               tw->tts_speak_last_utterance = utterance_id;
                if (utt_id) *utt_id = utterance_id;
                DEBUG("chunk size (%d) added utterance id:%d\n", (int)strlen(utf8_line), utterance_id);
        }
        return SUCCESS;
 }
 
-static void stop_speaking(Service_Data *sd)
+static void stop_speaking(TWData *tw)
 {
-       if (tts_speak_running) {
-               tts_speak_running = EINA_FALSE;
-               int ret = tts_stop(sd->tts);
+       if (tw->tts_speak_running) {
+               tw->tts_speak_running = EINA_FALSE;
+               int ret = tts_stop(tw->tts);
                if (TTS_ERROR_NONE != ret)
                        DEBUG("Fail to stop TTS: result(%d)", ret);
        }
@@ -454,9 +487,10 @@ static void stop_speaking(Service_Data *sd)
  * FAILURE_RECOVERABLE if the TTS was not ready to accept requests (and the function can be called again)
  */
 static Play_Read_Command_Status
-send_command_to_tts(Service_Data *sd, Read_Command *command, tts_state_e state)
+send_command_to_tts(TWData *tw, tts_state_e state)
 {
-       if (!sd || !command) return FAILURE_NOT_RECOVERABLE;
+       Read_Command *command = tw->last_read_command;
+       if (!command) return FAILURE_NOT_RECOVERABLE;
 
        if (command->chain_info) command->chain_info->reading_started_at_all = 1;
        Read_Context *ctx = &command->context;
@@ -478,7 +512,7 @@ send_command_to_tts(Service_Data *sd, Read_Command *command, tts_state_e state)
                                return FAILURE_NOT_RECOVERABLE;
                        }
                        remaining_text += consumed_chars;
-                       int result = send_chunk_to_tts(sd, utf8_line, &ctx->last_id);
+                       int result = send_chunk_to_tts(tw, utf8_line, &ctx->last_id);
                        if (result == FAILURE_NOT_RECOVERABLE) {
                                remaining_text = NULL;
                        } else {
@@ -497,17 +531,23 @@ send_command_to_tts(Service_Data *sd, Read_Command *command, tts_state_e state)
                if (chunk_accepted) {
                        DEBUG("Chunk accepted id %d", ctx->last_id);
                        command->is_playing = EINA_TRUE;
-                       if (state == TTS_STATE_READY) tts_play(sd->tts);
+                       if (state == TTS_STATE_READY) tts_play(tw->tts);
 
 #ifndef SCREEN_READER_TV
-                       device_display_lock_request(sd->system_data);
-                       if (display_lock_release_timer)
-                               ecore_timer_reset(display_lock_release_timer);
+                       /* TODO This is not proper way and place to do this. */
+                       Service_Data *sd = get_pointer_to_service_data_struct();
+                       if (!sd || !sd->system_data) {
+                               ERROR("Critical: Service_Data or System_Data is null");
+                       } else {
+                               device_display_lock_request(sd->system_data);
+                       }
+                       if (tw->display_lock_release_timer)
+                               ecore_timer_reset(tw->display_lock_release_timer);
 #endif
                        return SUCCESS;
                }
        } else {
-               DEBUG("TTS state is %s, %spaused", get_tts_state(state), pause_state ? "" : "NOT ");
+               DEBUG("TTS state is %s, %spaused", get_tts_state(state), tw->pause_state ? "" : "NOT ");
        }
        return FAILURE_RECOVERABLE;
 }
@@ -517,19 +557,19 @@ send_command_to_tts(Service_Data *sd, Read_Command *command, tts_state_e state)
  *
  * @return bool true iff there is a read command to be processed
  */
-static bool have_read_command(void)
+static bool have_read_command(TWData *tw)
 {
-       return last_read_command != NULL || eina_list_count(read_command_queue) > 0;
+       return tw->last_read_command != NULL || eina_list_count(tw->read_command_queue) > 0;
 }
 
-static void tts_speak_request(void);
-static Ecore_Timer *delay_timer = NULL;
 
-static Eina_Bool tts_speak_delay_finished_cb(void *d)
+static Eina_Bool tw_speak_delay_finished_cb(void *d)
 {
-       delay_timer = NULL;
-       if (last_read_command == d)
-               tts_speak_request();
+       TWData *tw = tw_get_instance();
+
+       tw->delay_timer = NULL;
+       if (tw->last_read_command == d)
+               tw_speak_request(tw);
        return ECORE_CALLBACK_CANCEL;
 }
 
@@ -546,50 +586,47 @@ static Eina_Bool tts_speak_delay_finished_cb(void *d)
  * This function is invoked in two places: when an item is added to the command queue,
  * or TTS state change has happened.
  */
-static void tts_speak_do(void)
+static void tw_speak_do(TWData *tw)
 {
-       DEBUG("[START] tts_speak_do");
-       Service_Data *sd = get_pointer_to_service_data_struct();
-       if (!sd || !have_read_command()) return;
-
-       while (have_read_command()) {
-               Read_Command *command = read_command_queue ? read_command_queue->data : NULL;
+       DEBUG("[START] tw_speak_do");
+       while (have_read_command(tw)) {
+               Read_Command *command = tw->read_command_queue ? tw->read_command_queue->data : NULL;
 
-               if (!command && last_read_command && (last_read_command->time_to_speak || last_read_command->delay_to_speak)) {
-                       if (!last_read_command->time_to_speak && last_read_command->delay_to_speak)
-                               last_read_command->time_to_speak = get_tick_count(last_read_command->delay_to_speak);
+               if (!command && tw->last_read_command && (tw->last_read_command->time_to_speak || tw->last_read_command->delay_to_speak)) {
+                       if (!tw->last_read_command->time_to_speak && tw->last_read_command->delay_to_speak)
+                               tw->last_read_command->time_to_speak = get_tick_count(tw->last_read_command->delay_to_speak);
                        // we substract to avoid wrap around problem (when one time will be at oxffffffff and the next one at 0x00000000,
                        // thus messing up comparision). time_to_speak is "ahead" (in future) to now only if after substraction
                        // we get positive number. since it's unsigned we check against 0x7fffffff. this will work even if
                        // unsigned int type will be 64 bit and 0x7fffffff is almost 600 hours, unlikely to every be mistaken.
                        unsigned int now = get_tick_count(0);
-                       unsigned int diff = last_read_command->time_to_speak - now;
+                       unsigned int diff = tw->last_read_command->time_to_speak - now;
                        if (diff < 0x7fffffff) {
-                               if (delay_timer) ecore_timer_del(delay_timer);
+                               if (tw->delay_timer) ecore_timer_del(tw->delay_timer);
                                DEBUG("delaying speaking for %d ms", diff);
-                               delay_timer = ecore_timer_add(diff * 0.001, tts_speak_delay_finished_cb, last_read_command);
+                               tw->delay_timer = ecore_timer_add(diff * 0.001, tw_speak_delay_finished_cb, tw->last_read_command);
                                break;
                        }
-                       last_read_command->time_to_speak = last_read_command->delay_to_speak = 0;
+                       tw->last_read_command->time_to_speak = tw->last_read_command->delay_to_speak = 0;
                        DEBUG("resuming delayed speaking");
                }
 
                tts_state_e state;
-               tts_get_state(sd->tts, &state);
+               tts_get_state(tw->tts, &state);
 
-               DEBUG("tts_speak_do: queue length %d, head(%s)", eina_list_count(read_command_queue), sprintf_command(last_read_command));
+               DEBUG("tw_speak_do: queue length %d, head(%s)", eina_list_count(tw->read_command_queue), sprintf_command(tw->last_read_command));
                // Should the current command be skipped?
-               if ((state == TTS_STATE_PLAYING || state == TTS_STATE_PAUSED) && command && can_discard(last_read_command, command) && !command->delay_to_speak) {
+               if ((state == TTS_STATE_PLAYING || state == TTS_STATE_PAUSED) && command && can_discard(tw->last_read_command, command) && !command->delay_to_speak) {
                        DEBUG("Stopping TTS");
-                       stop_speaking(sd);
+                       stop_speaking(tw);
                        state = TTS_STATE_READY;
-                       overwrite_last_read_command_with(NULL);
+                       overwrite_last_read_command_with(tw, NULL);
                }
 
                // Send the command to the tts, perhaps in chunks.
-               if (!last_read_command || send_command_to_tts(sd, last_read_command, state) == FAILURE_NOT_RECOVERABLE) {
+               if (!tw->last_read_command || send_command_to_tts(tw, state) == FAILURE_NOT_RECOVERABLE) {
                        // If the command failed, take next from the queue.
-                       Read_Command *command = get_read_command_from_queue(&read_command_queue);
+                       Read_Command *command = get_read_command_from_queue(tw, &(tw->read_command_queue));
                        if (command) {
                                char text[64];
                                g_strlcpy(text, command->context.text, 63);
@@ -599,29 +636,27 @@ static void tts_speak_do(void)
                                DEBUG("TTS_STATE_NAME: %s", get_tts_state(state));
                                DEBUG("START COMMAND PROCESSING");
                        }
-                       overwrite_last_read_command_with(command);
+                       overwrite_last_read_command_with(tw, command);
                } else break;
        } // while (have something to read)
-       DEBUG("[END] tts_speak_do");
+       DEBUG("[END] tw_speak_do");
 }
 
-// TODO: this is not synchronized, but it probably should
-static volatile bool request_speak_do = false;
-static volatile bool running = false;
-static void tts_speak_request(void)
+static void tw_speak_request(TWData *tw)
 {
-       DEBUG("[START] tts_speak_request %srunning", running ? "" : "not ");
-       if (running) {
-               request_speak_do = true;
+       DEBUG("[START] tw_speak_request %srunning", tw->running ? "" : "not ");
+
+       if (tw->running) {
+               tw->request_speak_do = true;
                return;
        }
-       running = true;
+       tw->running = true;
        do {
-               request_speak_do = false;
-               tts_speak_do();
-       } while (request_speak_do);
-       running = false;
-       DEBUG("[END] tts_speak_request");
+               tw->request_speak_do = false;
+               tw_speak_do(tw);
+       } while (tw->request_speak_do);
+       tw->running = false;
+       DEBUG("[END] tw_speak_request");
 }
 
 static int get_next_seq()
@@ -672,9 +707,11 @@ static char* duplicate_and_sanitize(const char *text)
 }
 
 Read_Command *
-tts_speak_customized(char *text_to_speak, Eina_Bool want_discard_previous_reading,
+tw_speak_customized(char *text_to_speak, Eina_Bool want_discard_previous_reading,
                                         Eina_Bool discardable, AtspiAccessible *obj, unsigned int delay)
 {
+       TWData *tw = tw_get_instance();
+
        if (text_to_speak == NULL) return NULL;
 
        char *text_to_speak_sanitized = duplicate_and_sanitize(text_to_speak);
@@ -715,15 +752,14 @@ tts_speak_customized(char *text_to_speak, Eina_Bool want_discard_previous_readin
                free(text_to_speak_sanitized);
                return NULL;
        }
-       Service_Data *sd = get_pointer_to_service_data_struct();
-       if (!sd || !sd->tts)
+       if (!tw->tts)
        {
-               ERROR("Problem with accessing service data struct!");
+               ERROR("Problem with accessing tts!");
                free(text_to_speak_sanitized);
                return NULL;
        }
        tts_state_e state;
-       tts_get_state(sd->tts, &state);
+       tts_get_state(tw->tts, &state);
        char text[64];
        g_strlcpy(text, text_to_speak_sanitized, 63);
        text[63] = 0;
@@ -751,7 +787,7 @@ tts_speak_customized(char *text_to_speak, Eina_Bool want_discard_previous_readin
        rc->time_to_speak = 0;
        rc->delay_to_speak = delay;
        if (delay) {
-               Read_Command *previous = read_command_queue ? read_command_queue->data : last_read_command;
+               Read_Command *previous = tw->read_command_queue ? tw->read_command_queue->data : tw->last_read_command;
                if (previous) {
                        Read_Command_Chain_Info *chain = g_malloc0(sizeof(Read_Command_Chain_Info));
                        if (chain) {
@@ -762,27 +798,27 @@ tts_speak_customized(char *text_to_speak, Eina_Bool want_discard_previous_readin
                        previous->chain_info = rc->chain_info = chain;
                }
        }
-       DEBUG("BEFORE ADD: (#%d, last %s)", eina_list_count(read_command_queue),
-                 read_command_queue ? sprintf_command(read_command_queue->data) : "empty");
-       if (want_discard_previous_reading) compress_command_queue(&read_command_queue, rc);
+       DEBUG("BEFORE ADD: (#%d, last %s)", eina_list_count(tw->read_command_queue),
+                 tw->read_command_queue ? sprintf_command(tw->read_command_queue->data) : "empty");
+       if (want_discard_previous_reading) compress_command_queue(&(tw->read_command_queue), rc);
        // There is no eina_list_empty()...
-       bool queue_head_changed = eina_list_last(read_command_queue) == NULL;
-       read_command_queue = eina_list_append(read_command_queue, rc);
+       bool queue_head_changed = eina_list_last(tw->read_command_queue) == NULL;
+       tw->read_command_queue = eina_list_append(tw->read_command_queue, rc);
        DEBUG("AFTER ADD: %s (head %schanged)",
-                 read_command_queue ? sprintf_command(read_command_queue->data) : "(empty)",
+                 tw->read_command_queue ? sprintf_command(tw->read_command_queue->data) : "(empty)",
                  queue_head_changed ? "" : "un");
        // Only request housekeeping if list head changed
-       if (queue_head_changed) tts_speak_request();
+       if (queue_head_changed) tw_speak_request(tw);
        DEBUG("tts_speak_customized: END");
        return rc;
 }
 
-Read_Command *tts_speak(char *text_to_speak, Eina_Bool want_discard_previous_reading)
+Read_Command *tw_speak(char *text_to_speak, Eina_Bool want_discard_previous_reading)
 {
-       return tts_speak_customized(text_to_speak, want_discard_previous_reading, EINA_TRUE, NULL, 0);
+       return tw_speak_customized(text_to_speak, want_discard_previous_reading, EINA_TRUE, NULL, 0);
 }
 
-static void tts_utt_started_cb(tts_h tts, int utt_id, void *user_data)
+static void tw_utt_started_cb(tts_h tts, int utt_id, void *user_data)
 {
        DEBUG("Utterance started : utt id(%d) \n", utt_id);
        return;
@@ -791,181 +827,191 @@ static void tts_utt_started_cb(tts_h tts, int utt_id, void *user_data)
 #ifndef SCREEN_READER_TV
 static Eina_Bool _display_lock_release_timer_cb(void *data)
 {
-       Service_Data *sd = (Service_Data *)data;
+       TWData *tw = (TWData*)data;
 
-       if (last_read_command && last_read_command->is_playing) {
+       if (tw->last_read_command && tw->last_read_command->is_playing) {
                return ECORE_CALLBACK_RENEW;
        }
 
+       /* TODO This not a proper way and place to do this. */
+       Service_Data *sd = get_pointer_to_service_data_struct();
        if (!sd || !sd->system_data) {
                ERROR("Critical: Service_Data or System_Data is null");
-       } else
+       } else {
                device_display_lock_release(sd->system_data);
+       }
 
-       display_lock_release_timer = NULL;
+       tw->display_lock_release_timer = NULL;
        return ECORE_CALLBACK_CANCEL;
 }
 #endif
 
-static void tts_utt_completed_cb(tts_h tts, int utt_id, void *user_data)
+static void tw_utt_completed_cb(tts_h tts, int utt_id, void *user_data)
 {
        DEBUG("Utterance completed : utt id(%d) \n", utt_id);
+       TWData *tw = (TWData*)user_data;
 
-       if (tts_speak_last_utterance == utt_id)
-               tts_speak_running = EINA_FALSE;
-       if (last_read_command && last_read_command->context.last_id == utt_id) {
+       if (tw->tts_speak_last_utterance == utt_id)
+               tw->tts_speak_running = EINA_FALSE;
+       if (tw->last_read_command && tw->last_read_command->context.last_id == utt_id) {
                DEBUG("LAST UTTERANCE");
-               if (last_read_command->chain_info) --last_read_command->chain_info->chunks_yet_to_read;
+               if (tw->last_read_command->chain_info) --(tw->last_read_command->chain_info->chunks_yet_to_read);
 
 #ifndef SCREEN_READER_TV
-               if (!last_read_command->is_screen_turn_off) {
-                       if (display_lock_release_timer) ecore_timer_del(display_lock_release_timer);
+               if (!tw->last_read_command->is_screen_turn_off) {
+                       if (tw->display_lock_release_timer) ecore_timer_del(tw->display_lock_release_timer);
                        DEBUG("resetting timer");
-                       display_lock_release_timer = ecore_timer_add(vc_get_lcd_backlight_timeout() < 0.01 ? 0.01 : vc_get_lcd_backlight_timeout(),
+                       tw->display_lock_release_timer = ecore_timer_add(vc_get_lcd_backlight_timeout() < 0.01 ? 0.01 : vc_get_lcd_backlight_timeout(),
                                _display_lock_release_timer_cb, user_data);
                }
-               pause_state = EINA_FALSE;
+               tw->pause_state = EINA_FALSE;
 
-               if (on_utterance_end)
-                       on_utterance_end(on_utterance_end_user_data);
+               if (tw->on_utterance_end)
+                       tw->on_utterance_end(tw->on_utterance_end_user_data);
 #endif
-               last_read_command->is_playing = EINA_FALSE;
-               Service_Data *sd = (Service_Data *)user_data;
-               stop_speaking(sd);
-               overwrite_last_read_command_with(NULL);
+               tw->last_read_command->is_playing = EINA_FALSE;
+               stop_speaking(tw);
+               overwrite_last_read_command_with(tw, NULL);
        }
-       tts_speak_request();
+       tw_speak_request(tw);
        return;
 }
-
-bool tts_init(void *data)
+static
+void tw_init_internal(TWData *tw)
 {
        DEBUG("--------------------- TTS_init START ---------------------");
-       Service_Data *sd = data;
 
-       int r = tts_create(&sd->tts);
+       int r = tts_create(&tw->tts);
        DEBUG("Create tts %d (%s)", r, get_tts_error(r));
 
        if (TTS_ERROR_NONE != r) {
                ERROR("Fail to create tts (%s)", get_tts_error(r));
-               return false;
+               return;
        }
-
-       r = tts_set_mode(sd->tts, TTS_MODE_SCREEN_READER);
+#ifndef SCREEN_READER_TV
+       tw->display_lock_release_timer = NULL;
+#endif
+       tw->pause_state = EINA_FALSE;
+       tw->read_command_queue = NULL;
+       tw->last_read_command = NULL;
+       tw->on_utterance_end = NULL;
+       tw->on_utterance_end_user_data = NULL;
+       tw->tts_speak_running = false;
+       tw->tts_speak_last_utterance = -1;
+       tw->delay_timer = NULL;
+       tw->request_speak_do = false;
+       tw->running = false;
+
+       r = tts_set_mode(tw->tts, TTS_MODE_SCREEN_READER);
        DEBUG("Set tts mode SR %d (%s)", r, get_tts_error(r));
 
-       r = tts_prepare(sd->tts);
+       r = tts_prepare(tw->tts);
        tts_state_e state;
-       tts_get_state(sd->tts, &state);
+       tts_get_state(tw->tts, &state);
        DEBUG("Prepare tts %d (%s), state %d (%s)", r, get_tts_error(r), state, get_tts_state(state));
 
-       r = tts_set_state_changed_cb(sd->tts, state_changed_cb, sd);
+       r = tts_set_state_changed_cb(tw->tts, tw_state_changed_cb, tw);
        if (TTS_ERROR_NONE != r) {
                ERROR("Fail to set state changed cb (%s)", get_tts_error(r));
        }
-       r = tts_set_utterance_started_cb(sd->tts, tts_utt_started_cb, sd);
+       r = tts_set_utterance_started_cb(tw->tts, tw_utt_started_cb, tw);
        if (TTS_ERROR_NONE != r) {
                ERROR("Fail to set utterance started cb (%s)", get_tts_error(r));
        }
-       r = tts_set_utterance_completed_cb(sd->tts, tts_utt_completed_cb, sd);
+       r = tts_set_utterance_completed_cb(tw->tts, tw_utt_completed_cb, tw);
        if (TTS_ERROR_NONE != r) {
                ERROR("Fail to set utterance completed cb (%s)", get_tts_error(r));
        }
+
+       tw->init = 1;
        DEBUG("---------------------- TTS_init END ----------------------\n\n");
-       return true;
 }
 
-void tts_shutdown(void *data)
+static
+TWData *tw_get_instance(void) {
+       static TWData instance = {0};
+       if (!instance.init)
+               tw_init_internal(&instance);
+
+       return &instance;
+}
+
+bool tw_init(void)
+{
+       DEBUG("--------------------- TTS_init START ---------------------");
+       return tw_get_instance()->init;
+}
+
+void tw_shutdown(void)
 {
+       TWData *tw = tw_get_instance();
 #ifndef SCREEN_READER_TV
-       if (display_lock_release_timer) {
-               ecore_timer_del(display_lock_release_timer);
-               display_lock_release_timer = NULL;
+       if (tw->display_lock_release_timer) {
+               ecore_timer_del(tw->display_lock_release_timer);
+               tw->display_lock_release_timer = NULL;
        }
 #endif
 
-       Service_Data *sd = data;
-       if (!sd) {
-               ERROR("Invalid parameter");
-               return;
-       }
-       g_free(sd->current_value);
-       sd->current_value = NULL;
-       stop_speaking(sd);
+       stop_speaking(tw);
+       tts_destroy(tw->tts);
+       tw->tts = NULL;
+       tw->init = 0;
 }
 
-void tts_purge(Eina_Bool only_discardables)
+void tw_purge(Eina_Bool only_discardables)
 {
        DEBUG("BEGIN");
-       purge_commands_from_queue(&read_command_queue, only_discardables);
-       if (last_read_command && last_read_command->is_playing && (last_read_command->discardable || !only_discardables)) {
-               Service_Data *sd = get_pointer_to_service_data_struct();
-               stop_speaking(sd);
-               overwrite_last_read_command_with(NULL);
+       TWData *tw = tw_get_instance();
+       purge_commands_from_queue(&(tw->read_command_queue), only_discardables);
+       if (tw->last_read_command && tw->last_read_command->is_playing && (tw->last_read_command->discardable || !only_discardables)) {
+               stop_speaking(tw);
+               overwrite_last_read_command_with(tw, NULL);
        }
        DEBUG("END");
 }
 
-Eina_Bool tts_pause_get(void)
+Eina_Bool tw_pause_get(void)
 {
-       DEBUG("PAUSE STATE: %d", pause_state);
-       return pause_state;
+       TWData *tw = tw_get_instance();
+       DEBUG("PAUSE STATE: %d", tw->pause_state);
+       return tw->pause_state;
 }
 
-void tts_stop_set(void)
+void tw_stop_set(void)
 {
-       if (last_read_command && last_read_command->discardable) {
-               Service_Data *sd = get_pointer_to_service_data_struct();
-               stop_speaking(sd);
-               overwrite_last_read_command_with(NULL);
+       TWData *tw = tw_get_instance();
+       if (tw->last_read_command && tw->last_read_command->discardable) {
+               stop_speaking(tw);
+               overwrite_last_read_command_with(tw, NULL);
        }
 }
 
-Eina_Bool tts_pause_set(Eina_Bool pause_switch)
+Eina_Bool tw_pause_set(Eina_Bool pause_switch)
 {
-       Service_Data *sd = get_pointer_to_service_data_struct();
-       if (!sd)
-               return EINA_FALSE;
+       TWData *tw = tw_get_instance();
 
        if (pause_switch) {
-               pause_state = EINA_TRUE;
+               tw->pause_state = EINA_TRUE;
 
-               if (tts_pause(sd->tts)) {
-                       pause_state = EINA_FALSE;
+               if (tts_pause(tw->tts)) {
+                       tw->pause_state = EINA_FALSE;
                        return EINA_FALSE;
                }
-               if (last_read_command) {
-                       _reading_status_notify(READING_PAUSED, last_read_command);
+               if (tw->last_read_command) {
+                       _reading_status_notify(READING_PAUSED, tw->last_read_command);
                }
        } else if (!pause_switch) {
                // TODO(t.wozniak): close the state machine (non-empty queue and empty TTS).
-               pause_state = EINA_FALSE;
+               tw->pause_state = EINA_FALSE;
 
-               if (tts_play(sd->tts)) {
-                       pause_state = EINA_TRUE;
+               if (tts_play(tw->tts)) {
+                       tw->pause_state = EINA_TRUE;
                        return EINA_FALSE;
                }
-               if (last_read_command) {
-                       _reading_status_notify(READING_RESUMED, last_read_command);
+               if (tw->last_read_command) {
+                       _reading_status_notify(READING_RESUMED, tw->last_read_command);
                }
        }
        return EINA_TRUE;
 }
 
-void state_changed_cb(tts_h tts, tts_state_e previous, tts_state_e current, void *user_data)
-{
-       if (pause_state) {
-               DEBUG("TTS is currently paused. Resume to start reading");
-               return;
-       }
-
-       DEBUG("++++++++++++++++state_changed_cb++++++++++++++++++");
-       DEBUG("current state:%s and previous state:%s\n", get_tts_state(current), get_tts_state(previous));
-       if (current == TTS_STATE_READY && previous == TTS_STATE_PLAYING
-                       && last_read_command && last_read_command->is_playing) {
-               overwrite_last_read_command_with(NULL);
-       }
-
-       if (TTS_STATE_READY == current)
-               tts_speak_request();
-}