mobile-lua: add additional LABELLED_BY relation
[profile/tv/apps/native/screen-reader.git] / src / screen_reader_spi.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 <stdio.h>
20 #include "screen_reader_spi.h"
21 #include "screen_reader_tts.h"
22 #include "logger.h"
23 #include "lua_engine.h"
24 #ifdef RUN_IPC_TEST_SUIT
25 #include "test_suite/test_suite.h"
26 #endif
27
28 #define EPS 0.000000001
29
30 /** @brief Service_Data used as screen reader internal data struct*/
31 static Service_Data *service_data;
32
33 /**
34  * @brief Debug function. Print current toolkit version/event
35  * type/event source/event detail1/event detail2
36  *
37  * @param AtspiEvent instance
38  *
39  */
40 static void display_info(const AtspiEvent * event)
41 {
42         AtspiAccessible *source = event->source;
43         gchar *name = atspi_accessible_get_name(source, NULL);
44         gchar *role = atspi_accessible_get_localized_role_name(source, NULL);
45         gchar *toolkit = atspi_accessible_get_toolkit_name(source, NULL);
46
47         DEBUG("--------------------------------------------------------");
48         DEBUG("Toolkit: %s; Event_type: %s; (%d, %d)", toolkit, event->type, event->detail1, event->detail2);
49         DEBUG("Name: %s; Role: %s", name, role);
50         DEBUG("--------------------------------------------------------");
51 }
52
53 static char *spi_on_state_changed_get_text(AtspiEvent * event, void *user_data)
54 {
55         Service_Data *sd = (Service_Data *) user_data;
56         sd->currently_focused = event->source;
57
58         return lua_engine_describe_object(sd->currently_focused);
59 }
60
61 static char *spi_on_caret_move_get_text(AtspiEvent * event, void *user_data)
62 {
63         Service_Data *sd = (Service_Data *) user_data;
64         sd->currently_focused = event->source;
65         char *return_text;
66
67         AtspiText *text_interface = atspi_accessible_get_text_iface(sd->currently_focused);
68         if (text_interface) {
69                 DEBUG("->->->->->-> WIDGET CARET MOVED: %s <-<-<-<-<-<-<-", atspi_accessible_get_name(sd->currently_focused, NULL));
70
71                 int char_count = (int)atspi_text_get_character_count(text_interface, NULL);
72                 int caret_pos = atspi_text_get_caret_offset(text_interface, NULL);
73                 if (!caret_pos) {
74                         DEBUG("MIN POSITION REACHED");
75                         if (asprintf(&return_text, "%s %s", (char *)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL), _("IDS_REACHED_MIN_POS")) < 0) {
76                                 ERROR(MEMORY_ERROR);
77                                 return NULL;
78                         }
79                 } else if (char_count == caret_pos) {
80                         DEBUG("MAX POSITION REACHED");
81                         if (asprintf(&return_text, "%s %s", (char *)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL), _("IDS_REACHED_MAX_POS")) < 0) {
82                                 ERROR(MEMORY_ERROR);
83                                 return NULL;
84                         }
85                 } else {
86                         if (asprintf(&return_text, "%s", (char *)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL)) < 0) {
87                                 ERROR(MEMORY_ERROR);
88                                 return NULL;
89                         }
90                 }
91         } else {
92                 ERROR(MEMORY_ERROR);
93                 return NULL;
94         }
95         return return_text;
96 }
97
98 static char *spi_on_value_changed_get_text(AtspiEvent * event, void *user_data)
99 {
100         Service_Data *sd = (Service_Data *) user_data;
101         char *text_to_read = NULL;
102
103         sd->currently_focused = event->source;
104
105         AtspiValue *value_interface = atspi_accessible_get_value_iface(sd->currently_focused);
106         if (value_interface) {
107                 DEBUG("->->->->->-> WIDGET VALUE CHANGED: %s <-<-<-<-<-<-<-", atspi_accessible_get_name(sd->currently_focused, NULL));
108
109                 double current_temp_value = (double)atspi_value_get_current_value(value_interface, NULL);
110                 if (abs(current_temp_value - atspi_value_get_maximum_value(value_interface, NULL)) < EPS) {
111                         DEBUG("MAX VALUE REACHED");
112                         if (asprintf(&text_to_read, "%.2f %s", current_temp_value, _("IDS_REACHED_MAX_VAL")) < 0) {
113                                 ERROR(MEMORY_ERROR);
114                                 return NULL;
115                         }
116                 } else if (abs(current_temp_value - atspi_value_get_minimum_value(value_interface, NULL)) < EPS) {
117                         DEBUG("MIN VALUE REACHED");
118                         if (asprintf(&text_to_read, "%.2f %s", current_temp_value, _("IDS_REACHED_MIN_VAL")) < 0) {
119                                 ERROR(MEMORY_ERROR);
120                                 return NULL;
121                         }
122                 } else {
123                         if (asprintf(&text_to_read, "%.2f", current_temp_value) < 0) {
124                                 ERROR(MEMORY_ERROR);
125                                 return NULL;
126                         }
127                 }
128         }
129
130         return text_to_read;
131 }
132
133 char *spi_event_get_text_to_read(AtspiEvent * event, void *user_data)
134 {
135         DEBUG("START");
136         Service_Data *sd = (Service_Data *) user_data;
137         char *text_to_read;
138
139         DEBUG("TRACK SIGNAL:%s", sd->tracking_signal_name);
140         DEBUG("WENT EVENT:%s", event->type);
141
142         if (!sd->tracking_signal_name) {
143                 ERROR("Invalid tracking signal name");
144                 return NULL;
145         }
146
147         if (!strncmp(event->type, sd->tracking_signal_name, strlen(event->type)) && event->detail1 == 1) {
148                 text_to_read = spi_on_state_changed_get_text(event, user_data);
149         } else if (!strncmp(event->type, CARET_MOVED_SIG, strlen(event->type))) {
150                 text_to_read = spi_on_caret_move_get_text(event, user_data);
151         } else if (!strncmp(event->type, VALUE_CHANGED_SIG, strlen(event->type))) {
152                 text_to_read = spi_on_value_changed_get_text(event, user_data);
153         } else {
154                 ERROR("Unknown event type");
155                 return NULL;
156         }
157
158         return text_to_read;
159 }
160
161 void spi_event_listener_cb(AtspiEvent * event, void *user_data)
162 {
163         DEBUG("START");
164         display_info(event);
165
166         if (!user_data) {
167                 ERROR("Invalid parameter");
168                 return;
169         }
170
171         char *text_to_read = spi_event_get_text_to_read(event, user_data);
172         if (!text_to_read) {
173                 ERROR("Can not prepare text to read");
174                 return;
175         }
176         DEBUG("SPEAK: %s", text_to_read);
177         tts_speak(text_to_read, EINA_TRUE);
178
179         free(text_to_read);
180         DEBUG("END");
181 }
182
183 /**
184   * @brief Initializer for screen-reader atspi listeners
185   *
186   * @param user_data screen-reader internal data
187   *
188 **/
189 void spi_init(Service_Data * sd)
190 {
191         if (!sd) {
192                 ERROR("Invalid parameter");
193                 return;
194         }
195         DEBUG("--------------------- SPI_init START ---------------------");
196         service_data = sd;
197
198         DEBUG(">>> Init lua engine<<<");
199         if (lua_engine_init(sd->lua_script_path))
200                 ERROR("Failed to init lua engine.");
201
202         DEBUG(">>> Creating listeners <<<");
203
204         sd->spi_listener = atspi_event_listener_new(spi_event_listener_cb, service_data, NULL);
205         if (sd->spi_listener == NULL) {
206                 DEBUG("FAILED TO CREATE spi state changed listener");
207         }
208         // ---------------------------------------------------------------------------------------------------
209
210         DEBUG("TRACKING SIGNAL:%s", sd->tracking_signal_name);
211
212         gboolean ret1 = atspi_event_listener_register(sd->spi_listener, sd->tracking_signal_name, NULL);
213         if (ret1 == false) {
214                 DEBUG("FAILED TO REGISTER spi focus/highlight listener");
215         }
216         GError *error = NULL;
217         gboolean ret2 = atspi_event_listener_register(sd->spi_listener, CARET_MOVED_SIG, &error);
218         if (ret2 == false) {
219                 DEBUG("FAILED TO REGISTER spi caret moved listener: %s", error ? error->message : "no error message");
220                 if (error)
221                         g_clear_error(&error);
222         }
223
224         gboolean ret3 = atspi_event_listener_register(sd->spi_listener, VALUE_CHANGED_SIG, &error);
225         if (ret3 == false) {
226                 DEBUG("FAILED TO REGISTER spi value changed listener: %s", error ? error->message : "no error message");
227                 if (error)
228                         g_clear_error(&error);
229         }
230
231         if (ret1 == true && ret2 == true && ret3 == true) {
232                 DEBUG("spi listener REGISTERED");
233         }
234
235         DEBUG("---------------------- SPI_init END ----------------------\n\n");
236 }
237
238 void spi_shutdown(Service_Data * sd)
239 {
240         lua_engine_shutdown();
241 }