[Fix prevent issue]
[profile/tv/apps/native/screen-reader.git] / src / smart_notification.c
1 #include <Ecore.h>
2 #include <Ecore_Evas.h>
3 #include <Evas.h>
4 #include <atspi/atspi.h>
5 #include <tone_player.h>
6 #include "logger.h"
7 #include "screen_reader_tts.h"
8 #include "screen_reader_haptic.h"
9 #include "smart_notification.h"
10
11 #define RED  "\x1B[31m"
12 #define RESET "\033[0m"
13
14 #define ITEMS_NOTIFICATION "Visible items from %d to %d"
15
16 static Eina_Bool status = EINA_FALSE;
17
18 static void _smart_notification_focus_chain_end(void);
19 static void _smart_notification_realized_items(int start_idx, int end_idx);
20
21 /**
22  * @brief Smart Notifications event handler
23  *
24  * @param nt Notification event type
25  * @param start_index int first visible items index smart_notification_realized_items
26  * @param end_index int last visible items index used for smart_notification_realized_items
27  */
28 void smart_notification(Notification_Type nt, int start_index, int end_index)
29 {
30    DEBUG("START");
31    if(!status)
32       return;
33
34    switch(nt)
35       {
36       case FOCUS_CHAIN_END_NOTIFICATION_EVENT:
37          _smart_notification_focus_chain_end();
38          break;
39       case REALIZED_ITEMS_NOTIFICATION_EVENT:
40          _smart_notification_realized_items(start_index, end_index);
41          break;
42       default:
43          DEBUG("Gesture type %d not handled in switch", nt);
44       }
45 }
46
47 /**
48  * @brief Used for getting first and last index of visible items
49  *
50  * @param scrollable_object AtspiAccessible object on which scroll was triggered
51  * @param start_index int first visible items index smart_notification_realized_items
52  * @param end_index int last visible items index used for smart_notification_realized_items
53  */
54 void get_realized_items_count(AtspiAccessible *scrollable_object, int *start_idx, int *end_idx)
55 {
56    DEBUG("START");
57    int count_child, jdx;
58    AtspiAccessible *child_iter;
59    AtspiStateType state =  ATSPI_STATE_SHOWING;
60
61    if(!scrollable_object)
62       {
63          DEBUG("No scrollable object");
64          return;
65       }
66
67    count_child = atspi_accessible_get_child_count(scrollable_object, NULL);
68
69    for(jdx = 0; jdx < count_child; jdx++)
70       {
71          child_iter = atspi_accessible_get_child_at_index(scrollable_object, jdx, NULL);
72          if (!child_iter) continue;
73
74          AtspiStateSet* state_set = atspi_accessible_get_state_set(child_iter);
75
76          gboolean is_visible = atspi_state_set_contains(state_set, state);
77          if(is_visible)
78             {
79                *start_idx = jdx;
80                DEBUG("Item with index %d is visible", jdx);
81             }
82          else
83             DEBUG("Item with index %d is NOT visible", jdx);
84       }
85    *end_idx = *start_idx + 8;
86 }
87
88 /**
89  * @brief Scroll-start/Scroll-end event callback
90  *
91  * @param event AtspiEvent
92  * @param user_data UNUSED
93  */
94
95 static void
96 _scroll_event_cb(AtspiEvent *event, gpointer user_data)
97 {
98    if(!status)
99       return;
100
101    int start_index, end_index;
102    start_index = 0;
103    end_index = 0;
104
105    gchar *role_name = atspi_accessible_get_role_name(event->source, NULL);
106    fprintf(stderr, "Event: %s: %d, obj: %p: role: %s\n",
107            event->type, event->detail1, event->source,
108            role_name);
109    g_free(role_name);
110
111    if (!strcmp(event->type, "object:scroll-start"))
112       {
113          DEBUG("Scrolling started");
114          tts_speak("Scrolling started", EINA_TRUE);
115       }
116    else if (!strcmp(event->type, "object:scroll-end"))
117       {
118          DEBUG("Scrolling finished");
119          tts_speak("Scrolling finished", EINA_FALSE);
120          get_realized_items_count((AtspiAccessible *)event->source, &start_index, &end_index);
121          _smart_notification_realized_items(start_index, end_index);
122       }
123 }
124
125 /**
126  * @brief Initializer for smart notifications
127  *
128  *
129  */
130 void smart_notification_init(void)
131 {
132    DEBUG("Smart Notification init!");
133
134    AtspiEventListener *listener;
135
136    listener = atspi_event_listener_new(_scroll_event_cb, NULL, NULL);
137    atspi_event_listener_register(listener, "object:scroll-start", NULL);
138    atspi_event_listener_register(listener, "object:scroll-end", NULL);
139
140    haptic_module_init();
141
142    status = EINA_TRUE;
143 }
144
145 /**
146  * @brief Smart notifications shutdown
147  *
148  */
149 void smart_notification_shutdown(void)
150 {
151    status = EINA_FALSE;
152 }
153
154 /**
155  * @brief Smart notifications focus chain event handler
156  *
157  */
158 static void _smart_notification_focus_chain_end(void)
159 {
160    if(!status)
161       return;
162
163    DEBUG(RED"Smart notification - FOCUS CHAIN END"RESET);
164
165    tone_player_stop(0);
166    tone_player_start(TONE_TYPE_SUP_CONFIRM, SOUND_TYPE_MEDIA, 200, NULL);
167 }
168
169 /**
170  * @brief Smart notifications realized items event handler
171  *
172  */
173 static void _smart_notification_realized_items(int start_idx, int end_idx)
174 {
175    if(!status)
176       return;
177
178    if(start_idx == end_idx)
179       return;
180
181    DEBUG(RED"Smart notification - Visible items notification"RESET);
182
183    char buf[256];
184
185    snprintf(buf, sizeof(buf), ITEMS_NOTIFICATION, start_idx, end_idx);
186
187    tts_speak(strdup(buf), EINA_FALSE);
188 }