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