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