dlog
vconf
tts
-
+ capi-media-tone-player
+ capi-system-device
)
FOREACH(flag ${pkgs_CFLAGS})
#define ERROR(...) EINA_LOG_DOM_ERR(_eina_log_dom, __VA_ARGS__);
#define WARNING(...) EINA_LOG_DOM_WRN(_eina_log_dom, __VA_ARGS__);
+#define MEMORY_ERROR "Memory allocation error"
+
#endif /* end of include guard: LOGGER_H_ */
+#include <atspi/atspi.h>
+
void navigator_init(void);
void navigator_shutdown(void);
tts_h tts;
Eina_List *available_languages;
- char *text_to_say_text;
- char *description_text;
char *text_to_say_info;
char *current_value;
char *current_char;
--- /dev/null
+void haptic_module_init(void);
+void haptic_module_disconnect(void);
+void haptic_vibrate_start(void);
+void haptic_vibrate_stop(void);
--- /dev/null
+void system_notifications_init(void);
+void system_notifications_shutdown(void);
\ No newline at end of file
bool tts_init(void *data);
void state_changed_cb(tts_h tts, tts_state_e previous, tts_state_e current, void* user_data);
-bool update_supported_voices(void *data);
-void spi_prepare_text(void *data);
-void tts_append_text(void *data);
+Eina_Bool tts_speak(char *text_to_speak, Eina_Bool flush_switch);
void spi_stop(void *data);
#endif /* SCREEN_READER_TTS_H_ */
--- /dev/null
+#include "screen_reader.h"
+#include "screen_reader_haptic.h"
+#include "logger.h"
+
+enum _Notification_Type {
+ FOCUS_CHAIN_END_NOTIFICATION_EVENT,
+ REALIZED_ITEMS_NOTIFICATION_EVENT,
+};
+
+typedef enum _Notification_Type Notification_Type;
+
+void smart_notification_init(void);
+void smart_notification(Notification_Type nt, int start_index, int end_index);
+void smart_notification_shutdown(void);
<smack permit="atspi" type="rwx" />
<smack permit="e17" type="rwx" />
<smack permit="tts-server" type="rwx" />
+ <smack permit="media-controller-client" type="rwx" />
+ <smack permit="deviced" type="rwx" />
+ <smack permit="sensord" type="rwx" />
+ <smack permit="media-server" type="rwx" />
</permit>
<request>
<smack request="sdbd" type="rwx" />
<smack request="svi-data" type="rwx" />
<smack request="e17" type="rwx" />
<smack request="tts-server" type="rwx" />
+ <smack request="media-controller-client" type="rwx" />
+ <smack request="sound_server" type="rwx" />
+ <smack request="deviced" type="rwx" />
+ <smack request="sensord" type="rwx" />
+ <smack request="media-server" type="rwx" />
</request>
</define>
BuildRequires: pkgconfig(eina)
BuildRequires: pkgconfig(eldbus)
BuildRequires: pkgconfig(elementary)
+BuildRequires: pkgconfig(capi-media-tone-player)
+BuildRequires: pkgconfig(capi-system-device)
BuildRequires: tts
BuildRequires: tts-devel
BuildRequires: vconf
#include "object_cache.h"
#include "flat_navi.h"
#include "app_tracker.h"
+#include "smart_notification.h"
+#include "screen_reader_system.h"
#define QUICKPANEL_DOWN TRUE
#define QUICKPANEL_UP FALSE
role,
name,
oc->bounds->x, oc->bounds->y, oc->bounds->width, oc->bounds->height);
+ haptic_vibrate_start();
}
else {
name = atspi_accessible_get_name(obj, &err);
name,
role
);
+ haptic_vibrate_start();
}
g_free(role);
g_free(name);
obj = flat_navi_context_next(context);
// try next line
if (!obj)
- obj = flat_navi_context_line_next(context);
+ obj = flat_navi_context_line_next(context);
// try 'cycle' objects in context
if (!obj)
{
flat_navi_context_line_first(context);
obj = flat_navi_context_first(context);
+ smart_notification(FOCUS_CHAIN_END_NOTIFICATION_EVENT, 0, 0);
}
if (obj)
_current_highlight_object_set(obj);
{
flat_navi_context_line_last(context);
obj = flat_navi_context_last(context);
+ smart_notification(FOCUS_CHAIN_END_NOTIFICATION_EVENT, 0, 0);
}
if (obj)
_current_highlight_object_set(obj);
window_tracker_register(on_window_activate, NULL);
window_tracker_active_window_request();
app_tracker_init();
+ smart_notification_init();
+ system_notifications_init();
}
void navigator_shutdown(void)
object_cache_shutdown();
app_tracker_shutdown();
window_tracker_shutdown();
+ smart_notification_shutdown();
+ system_notifications_shutdown();
}
#include "screen_reader.h"
#include "screen_reader_tts.h"
+#include "screen_reader_vconf.h"
+#include "screen_reader_spi.h"
+#include "screen_reader_xml.h"
#include <vconf.h>
#include "logger.h"
.available_languages = NULL,
//Actions to do when tts state is 'ready'
- .say_text = false,
.update_language_list = false,
-
- .text_to_say_text = NULL,
.text_to_say_info = NULL
};
tts_stop(service_data->tts);
tts_unprepare(service_data->tts);
tts_destroy(service_data->tts);
- service_data->text_to_say_text = NULL;
- service_data->description_text = NULL;
service_data->text_from_dbus = NULL;
service_data->current_value = NULL;
--- /dev/null
+#include <device/haptic.h>
+#include "smart_notification.h"
+
+static haptic_device_h handle;
+static haptic_effect_h effect_handle;
+
+#define RED "\x1B[31m"
+#define RESET "\033[0m"
+
+/**
+ * @brief Initializer for haptic module
+ *
+ */
+void haptic_module_init(void)
+{
+ int num;
+
+ if(!device_haptic_get_count(&num))
+ {
+ DEBUG(RED"Haptic device received!"RESET);
+ }
+ else
+ {
+ ERROR("Cannot receive haptic device count");
+ return;
+ }
+
+ if(!device_haptic_open(0, &handle))
+ {
+ DEBUG(RED"Device connected!"RESET);
+ }
+ else
+ {
+ ERROR("Cannot open haptic device");
+ }
+}
+
+/**
+ * @brief Disconnect haptic handle
+ *
+ */
+void haptic_module_disconnect(void)
+{
+ if(!handle)
+ {
+ ERROR("Haptic handle lost");
+ return;
+ }
+ if(!device_haptic_close(handle))
+ {
+ DEBUG("Haptic disconnected");
+ }
+ else
+ {
+ ERROR("Haptic close error");
+ }
+}
+
+/**
+ * @brief Start vibrations
+ *
+ */
+void haptic_vibrate_start(void)
+{
+ if(!handle)
+ {
+ ERROR("Haptic handle lost");
+ return;
+ }
+ if(!device_haptic_vibrate(handle, 1000, 100, &effect_handle))
+ {
+ DEBUG(RED"Vibrations started!"RESET);
+ }
+ else
+ {
+ ERROR("Cannot start vibration");
+ }
+}
+
+/**
+ * @brief Stop vibrations
+ *
+ */
+void haptic_vibrate_stop(void)
+{
+ if(!handle)
+ {
+ ERROR("Haptic handle lost");
+ return;
+ }
+ if(!device_haptic_stop(handle, &effect_handle))
+ {
+ ERROR("Vibrations stopped!");
+ }
+ else
+ {
+ DEBUG(RED"Cannot stop vibration"RESET);
+ }
+}
* Author: m.skorupinsk
*/
+#define _GNU_SOURCE
+
+#include <stdio.h>
#include "screen_reader_spi.h"
#include "screen_reader_xml.h"
+#include "screen_reader_tts.h"
#include "logger.h"
#ifdef RUN_IPC_TEST_SUIT
- #include "test_suite/test_suite.h"
+ #include "test_suite/test_suite.h"
#endif
+#define NO_VALUE_INTERFACE "No value interface present"
+#define NO_TEXT_INTERFACE "No text interface present"
+
+/** @brief Service_Data used as screen reader internal data struct*/
static Service_Data *service_data;
typedef struct
{
- char *key;
- char *val;
+ char *key;
+ char *val;
} Attr;
+
+/**
+ * @brief Debug function. Print current toolkit version/event
+ * type/event source/event detail1/event detail2
+ *
+ * @param AtspiEvent instance
+ *
+ */
static void display_info(const AtspiEvent *event)
{
- AtspiAccessible *source = event->source;
- gchar *name= atspi_accessible_get_name(source, NULL);
- gchar *role= atspi_accessible_get_role_name(source, NULL);
- gchar *toolkit = atspi_accessible_get_toolkit_name(source, NULL);
-
- DEBUG("--------------------------------------------------------");
- DEBUG("Toolkit: %s; Event_type: %s; (%d, %d)", toolkit, event->type, event->detail1, event->detail2);
- DEBUG("Name: %s; Role: %s", name, role);
- DEBUG("--------------------------------------------------------");
+ AtspiAccessible *source = event->source;
+ gchar *name= atspi_accessible_get_name(source, NULL);
+ gchar *role= atspi_accessible_get_role_name(source, NULL);
+ gchar *toolkit = atspi_accessible_get_toolkit_name(source, NULL);
+
+ DEBUG("--------------------------------------------------------");
+ DEBUG("Toolkit: %s; Event_type: %s; (%d, %d)", toolkit, event->type, event->detail1, event->detail2);
+ DEBUG("Name: %s; Role: %s", name, role);
+ DEBUG("--------------------------------------------------------");
}
Eina_Bool double_click_timer_cb(void *data)
{
- Service_Data *sd = data;
- sd->clicked_widget = NULL;
+ Service_Data *sd = data;
+ sd->clicked_widget = NULL;
- return EINA_FALSE;
+ return EINA_FALSE;
}
+/**
+ * @brief Atspi tracking-signal callback passing current highlighted/focused
+ * accessible description to TTS
+ *
+ * @param AtspiEvent instance
+ * @param user_data screen-reader internal data
+ *
+**/
void spi_on_state_changed_cb(const AtspiEvent *event, void *user_data)
{
- DEBUG("START");
- DEBUG("STATE CHANGED");
- Service_Data *sd = user_data;
-
- display_info(event);
- if(strcmp(event->type, sd->tracking_signal_name) == 0 && event->detail1 == 1)
- {
- sd->currently_focused = event->source;
-
- DEBUG("->->->->->-> WIDGET GAINED HIGHLIGHT: %s <-<-<-<-<-<-<-",
- atspi_accessible_get_name(sd->currently_focused, NULL));
-
- sd->description_text = atspi_accessible_get_description(sd->currently_focused, NULL);
- if(strcmp(sd->description_text, "\0") == 0)
- {
- sd->description_text = atspi_accessible_get_name(sd->currently_focused, NULL);
- if(strcmp(sd->description_text, "\0") == 0)
- sd->description_text = (char*)atspi_accessible_get_role_name(sd->currently_focused, NULL);
- }
- sd->text_to_say_text = get_text_to_read("on_focus", sd->currently_focused);
- spi_prepare_text(sd);
- }
-
- DEBUG("END");
+ DEBUG("START");
+ DEBUG("STATE CHANGED");
+ Service_Data *sd = user_data;
+ char *text_to_read;
+
+ display_info(event);
+ if(strcmp(event->type, sd->tracking_signal_name) == 0 && event->detail1 == 1)
+ {
+ sd->currently_focused = event->source;
+
+ DEBUG("->->->->->-> WIDGET GAINED HIGHLIGHT: %s <-<-<-<-<-<-<-",
+ atspi_accessible_get_name(sd->currently_focused, NULL));
+
+ if(asprintf(&text_to_read, "%s", (char*)atspi_accessible_get_description(sd->currently_focused, NULL)) < 0)
+ {
+ ERROR(MEMORY_ERROR);
+ return;
+ }
+ else if(strcmp(text_to_read, "\0") == 0)
+ {
+ if(asprintf(&text_to_read, "%s", (char*)atspi_accessible_get_name(sd->currently_focused, NULL)) < 0)
+ {
+ ERROR(MEMORY_ERROR);
+ return;
+ }
+ else if(strcmp(text_to_read, "\0") == 0)
+ {
+ if(asprintf(&text_to_read, "%s", (char*)atspi_accessible_get_role_name(sd->currently_focused, NULL)) < 0)
+ {
+ ERROR(MEMORY_ERROR);
+ return;
+ }
+ }
+ }
+ tts_speak(text_to_read, EINA_FALSE);
+ free(text_to_read);
+ }
+
+ DEBUG("END");
}
+/**
+ * @brief Atspi caret-moved callback passing text to TTS
+ *
+ * @param AtspiEvent instance
+ * @param user_data screen-reader internal data
+ *
+**/
void spi_on_caret_move_cb(const AtspiEvent *event, void *user_data)
{
- DEBUG("START");
- DEBUG("CARET MOVED");
- Service_Data *sd = user_data;
- int char_count;
- gint caret_pos;
- char buf[256];
-
- display_info(event);
- if(strcmp(event->type, CARET_MOVED_SIG) == 0)
- {
- sd->currently_focused = event->source;
-
- AtspiText *text_interface = atspi_accessible_get_text(sd->currently_focused);
- if(text_interface)
- {
- DEBUG("->->->->->-> WIDGET CARET MOVED: %s <-<-<-<-<-<-<-",
- atspi_accessible_get_name(sd->currently_focused, NULL));
-
- char_count = (int)atspi_text_get_character_count(text_interface, NULL);
- caret_pos = atspi_text_get_caret_offset(text_interface, NULL);
- if(!caret_pos)
- {
- DEBUG("MIN POSITION REACHED");
- sprintf(buf, "%s %s", (char*)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL), MIN_POS_REACHED);
- }
- else if(char_count == caret_pos)
- {
- DEBUG("MAX POSITION REACHED");
- sprintf(buf, "%s %s", (char*)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL), MAX_POS_REACHED);
- }
- else
- sprintf(buf, "%s", (char*)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL));
-
- sd->text_to_say_text = strdup(buf);
- spi_prepare_text(sd);
- }
- }
-
- DEBUG("END");
+ DEBUG("START");
+ DEBUG("CARET MOVED");
+ Service_Data *sd = user_data;
+ int char_count;
+ gint caret_pos;
+ char *text_to_read;
+
+ display_info(event);
+ if(strcmp(event->type, CARET_MOVED_SIG) == 0)
+ {
+ sd->currently_focused = event->source;
+
+ AtspiText *text_interface = atspi_accessible_get_text(sd->currently_focused);
+ if(text_interface)
+ {
+ DEBUG("->->->->->-> WIDGET CARET MOVED: %s <-<-<-<-<-<-<-",
+ atspi_accessible_get_name(sd->currently_focused, NULL));
+
+ char_count = (int)atspi_text_get_character_count(text_interface, NULL);
+ caret_pos = atspi_text_get_caret_offset(text_interface, NULL);
+ if(!caret_pos)
+ {
+ DEBUG("MIN POSITION REACHED");
+ if(asprintf(&text_to_read, "%s %s", (char*)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL), MIN_POS_REACHED) < 0)
+ {
+ ERROR(MEMORY_ERROR);
+ return;
+ }
+ }
+ else if(char_count == caret_pos)
+ {
+ DEBUG("MAX POSITION REACHED");
+ if(asprintf(&text_to_read, "%s %s", (char*)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL), MAX_POS_REACHED) < 0)
+ {
+ ERROR(MEMORY_ERROR);
+ return;
+ }
+ }
+ else
+ {
+ if(asprintf(&text_to_read, "%s", (char*)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL)))
+ {
+ ERROR(MEMORY_ERROR);
+ return;
+ }
+ }
+ }
+ else
+ {
+ ERROR(MEMORY_ERROR);
+ return;
+ }
+ tts_speak(text_to_read, EINA_FALSE);
+ free(text_to_read);
+ }
+
+ DEBUG("END");
}
+/**
+ * @brief Atspi value-changed callback passing text to TTS
+ *
+ * @param AtspiEvent instance
+ * @param user_data screen-reader internal data
+ *
+**/
void spi_on_access_value_changed_cb(const AtspiEvent *event, void *user_data)
{
- DEBUG("START");
- DEBUG("STATE CHANGED");
- Service_Data *sd = user_data;
- double current_temp_value;
- char buf[256];
-
- display_info(event);
- if(strcmp(event->type, VALUE_CHANGED_SIG) == 0)
- {
- sd->currently_focused = event->source;
-
- AtspiValue *value_interface = atspi_accessible_get_value(sd->currently_focused);
- if(value_interface)
- {
- DEBUG("->->->->->-> WIDGET VALUE CHANGED: %s <-<-<-<-<-<-<-",
- atspi_accessible_get_name(sd->currently_focused, NULL));
-
- current_temp_value = (double)atspi_value_get_current_value(value_interface, NULL);
- if(current_temp_value == atspi_value_get_maximum_value(value_interface, NULL))
- {
- DEBUG("MAX VALUE REACHED");
- sprintf(buf, "%.2f %s", current_temp_value, MAX_REACHED);
- }
- else if(current_temp_value == atspi_value_get_minimum_value(value_interface, NULL))
- {
- DEBUG("MIN VALUE REACHED");
- sprintf(buf, "%.2f %s", current_temp_value, MIN_REACHED);
- }
- else
- sprintf(buf, "%.2f", current_temp_value);
-
- sd->text_to_say_text = strdup(buf);
- spi_prepare_text(sd);
- }
- }
- DEBUG("END");
+ DEBUG("START");
+ DEBUG("STATE CHANGED");
+ Service_Data *sd = user_data;
+ double current_temp_value;
+ char *text_to_read;
+ float epsilon = 0.000000001;
+
+ display_info(event);
+ if(strcmp(event->type, VALUE_CHANGED_SIG) == 0)
+ {
+ sd->currently_focused = event->source;
+
+ AtspiValue *value_interface = atspi_accessible_get_value(sd->currently_focused);
+ if(value_interface)
+ {
+ DEBUG("->->->->->-> WIDGET VALUE CHANGED: %s <-<-<-<-<-<-<-",
+ atspi_accessible_get_name(sd->currently_focused, NULL));
+
+ current_temp_value = (double)atspi_value_get_current_value(value_interface, NULL);
+ if(abs(current_temp_value - atspi_value_get_maximum_value(value_interface, NULL)) < epsilon)
+ {
+ DEBUG("MAX VALUE REACHED");
+ if(asprintf(&text_to_read, "%.2f %s", current_temp_value, MAX_REACHED) < 0)
+ {
+ ERROR(MEMORY_ERROR);
+ return;
+ }
+ }
+ else if(abs(current_temp_value - atspi_value_get_minimum_value(value_interface, NULL)) < epsilon)
+ {
+ DEBUG("MIN VALUE REACHED");
+ if(asprintf(&text_to_read, "%.2f %s", current_temp_value, MIN_REACHED) < 0)
+ {
+ ERROR(MEMORY_ERROR);
+ return;
+ }
+ }
+ else
+ {
+ if(asprintf(&text_to_read, "%.2f", current_temp_value) < 0)
+ {
+ ERROR(MEMORY_ERROR);
+ return;
+ }
+ }
+ }
+ else
+ {
+ ERROR(MEMORY_ERROR);
+ return;
+ }
+ tts_speak(text_to_read, EINA_FALSE);
+ free(text_to_read);
+ }
+ DEBUG("END");
}
+/**
+ * @brief Initializer for screen-reader atspi listeners
+ *
+ * @param user_data screen-reader internal data
+ *
+**/
void spi_init(Service_Data *sd)
{
- DEBUG( "--------------------- SPI_init START ---------------------");
- service_data = sd;
-
- DEBUG( ">>> Creating listeners <<<");
-
- sd->state_changed_listener = atspi_event_listener_new(spi_on_state_changed_cb, service_data, NULL);
- if(sd->state_changed_listener == NULL)
- {
- DEBUG("FAILED TO CREATE spi state changed listener")
- }
-
- sd->caret_moved_listener = atspi_event_listener_new(spi_on_caret_move_cb, service_data, NULL);
- if(sd->caret_moved_listener == NULL)
- {
- DEBUG("FAILED TO CREATE spi state changed listener")
- }
-
- sd->value_changed_listener = atspi_event_listener_new(spi_on_access_value_changed_cb, service_data, NULL);
- if(sd->value_changed_listener == NULL)
- {
- DEBUG("FAILED TO CREATE spi state changed listener")
- }
-
- // ---------------------------------------------------------------------------------------------------
-
- gboolean ret1 = atspi_event_listener_register(sd->state_changed_listener, sd->tracking_signal_name, NULL);
- if(ret1 == false)
- {
- DEBUG("FAILED TO REGISTER spi focus/highlight listener");
- }
-
- gboolean ret2 = atspi_event_listener_register(sd->caret_moved_listener, CARET_MOVED_SIG, NULL);
- if(ret2 == false)
- {
- DEBUG("FAILED TO REGISTER spi caret moved listener");
- }
-
- gboolean ret3 = atspi_event_listener_register(sd->value_changed_listener, VALUE_CHANGED_SIG, NULL);
- if(ret3 == false)
- {
- DEBUG("FAILED TO REGISTER spi value changed listener");
- }
-
- if(ret1 == true && ret2 == true && ret3 == true)
- {
- DEBUG("spi listener REGISTERED");
- }
-
- DEBUG( "---------------------- SPI_init END ----------------------\n\n");
+ DEBUG( "--------------------- SPI_init START ---------------------");
+ service_data = sd;
+
+ DEBUG( ">>> Creating listeners <<<");
+
+ sd->state_changed_listener = atspi_event_listener_new(spi_on_state_changed_cb, service_data, NULL);
+ if(sd->state_changed_listener == NULL)
+ {
+ DEBUG("FAILED TO CREATE spi state changed listener")
+ }
+
+ sd->caret_moved_listener = atspi_event_listener_new(spi_on_caret_move_cb, service_data, NULL);
+ if(sd->caret_moved_listener == NULL)
+ {
+ DEBUG("FAILED TO CREATE spi state changed listener")
+ }
+
+ sd->value_changed_listener = atspi_event_listener_new(spi_on_access_value_changed_cb, service_data, NULL);
+ if(sd->value_changed_listener == NULL)
+ {
+ DEBUG("FAILED TO CREATE spi state changed listener")
+ }
+
+ // ---------------------------------------------------------------------------------------------------
+
+ gboolean ret1 = atspi_event_listener_register(sd->state_changed_listener, sd->tracking_signal_name, NULL);
+ if(ret1 == false)
+ {
+ DEBUG("FAILED TO REGISTER spi focus/highlight listener");
+ }
+
+ gboolean ret2 = atspi_event_listener_register(sd->caret_moved_listener, CARET_MOVED_SIG, NULL);
+ if(ret2 == false)
+ {
+ DEBUG("FAILED TO REGISTER spi caret moved listener");
+ }
+
+ gboolean ret3 = atspi_event_listener_register(sd->value_changed_listener, VALUE_CHANGED_SIG, NULL);
+ if(ret3 == false)
+ {
+ DEBUG("FAILED TO REGISTER spi value changed listener");
+ }
+
+ if(ret1 == true && ret2 == true && ret3 == true)
+ {
+ DEBUG("spi listener REGISTERED");
+ }
+
+ DEBUG( "---------------------- SPI_init END ----------------------\n\n");
}
--- /dev/null
+#include <device/battery.h>
+#include <device/display.h>
+#include <device/callback.h>
+#include "screen_reader.h"
+#include "screen_reader_tts.h"
+#include "smart_notification.h"
+
+#define CHARGING "Battery charger connected"
+#define NOT_CHARGING "Battery charger disconnected"
+#define SCREEN_ON "Screen is on"
+#define SCREEN_OFF "Screen is off"
+#define BATTERY_LOW "Battery level is low"
+#define BATTERY_FULL "Battery level is full"
+#define BATTERY_CRITICAL "Battery level is critical"
+
+static void device_system_cb(device_callback_e type, void *value, void *user_data);
+
+/**
+ * @brief Initializer for smart notifications
+ *
+ */
+void system_notifications_init(void)
+{
+ // BATTERY LOW/FULL
+ device_add_callback(DEVICE_CALLBACK_BATTERY_LEVEL, device_system_cb, NULL);
+ // BATTERY CHARGING/NOT-CHARGING
+ device_add_callback(DEVICE_CALLBACK_BATTERY_CHARGING, device_system_cb, NULL);
+ // SCREEN OFF/ON
+ device_add_callback(DEVICE_CALLBACK_DISPLAY_STATE, device_system_cb, NULL);
+}
+
+/**
+ * @brief Initializer for smart notifications
+ *
+ */
+void system_notifications_shutdown(void)
+{
+ // BATTERY LOW/FULL
+ device_remove_callback(DEVICE_CALLBACK_BATTERY_LEVEL, device_system_cb);
+ // BATTERY CHARGING/NOT-CHARGING
+ device_remove_callback(DEVICE_CALLBACK_BATTERY_CHARGING, device_system_cb);
+ // SCREEN OFF/ON
+ device_remove_callback(DEVICE_CALLBACK_DISPLAY_STATE, device_system_cb);
+}
+
+/**
+ * @brief Device system callback handler
+ *
+ * @param type Device callback type
+ * @param value UNUSED
+ * @param user_data UNUSED
+ */
+static void device_system_cb(device_callback_e type, void *value, void *user_data)
+{
+ if(type == DEVICE_CALLBACK_BATTERY_LEVEL)
+ {
+ device_battery_level_e status;
+ if(device_battery_get_level_status(&status))
+ {
+ ERROR("Cannot get battery level status");
+ return;
+ }
+
+ if(status == DEVICE_BATTERY_LEVEL_LOW)
+ {
+ tts_speak(BATTERY_LOW, EINA_TRUE);
+ }
+ else if(status == DEVICE_BATTERY_LEVEL_CRITICAL)
+ {
+ tts_speak(BATTERY_CRITICAL, EINA_TRUE);
+ }
+ else if(status == DEVICE_BATTERY_LEVEL_FULL)
+ {
+ tts_speak(BATTERY_FULL, EINA_TRUE);
+ }
+ }
+ else if(type == DEVICE_CALLBACK_BATTERY_CHARGING)
+ {
+ bool charging;
+ if(device_battery_is_charging(&charging))
+ {
+ ERROR("Cannot check if battery is charging");
+ return;
+ }
+
+ if(charging)
+ {
+ tts_speak(CHARGING, EINA_FALSE);
+ }
+ else
+ {
+ tts_speak(NOT_CHARGING, EINA_FALSE);
+ }
+ }
+ else if(type == DEVICE_CALLBACK_DISPLAY_STATE)
+ {
+ display_state_e state;
+ if(device_display_get_state(&state))
+ {
+ ERROR("Cannot check if battery is charging");
+ return;
+ }
+
+ if(state == DISPLAY_STATE_NORMAL)
+ {
+ tts_speak(SCREEN_ON, EINA_FALSE);
+ }
+ else if(state == DISPLAY_STATE_SCREEN_OFF)
+ {
+ tts_speak(SCREEN_OFF, EINA_FALSE);
+ }
+ }
+}
/*
- * screen_reader_tts.c
- *
- * Created on: Feb 19, 2014
- * Author: m.skorupinsk
- */
+* screen_reader_tts.c
+*
+* Created on: Feb 19, 2014
+* Author: m.skorupinsk
+*/
+#define _GNU_SOURCE
+
#include <Ecore.h>
#include "screen_reader_tts.h"
#include "logger.h"
// ---------------------------- DEBUG HELPERS ------------------------------
+#define FLUSH_LIMIT 1
+
+static int last_utt_id;
+static Eina_Bool pause_state = EINA_FALSE;
+static Eina_Bool flush_flag = EINA_FALSE;
+
static char * get_tts_error( int r )
{
- switch( r )
- {
- case TTS_ERROR_NONE:
- {
- return "no error";
- }
- case TTS_ERROR_INVALID_PARAMETER:
- {
- return "inv param";
- }
- case TTS_ERROR_OUT_OF_MEMORY:
- {
- return "out of memory";
- }
- case TTS_ERROR_OPERATION_FAILED:
- {
- return "oper failed";
- }
- case TTS_ERROR_INVALID_STATE:
- {
- return "inv state";
- }
- default:
- {
- return "inny error";
- }
- }
+ switch( r )
+ {
+ case TTS_ERROR_NONE:
+ {
+ return "no error";
+ }
+ case TTS_ERROR_INVALID_PARAMETER:
+ {
+ return "inv param";
+ }
+ case TTS_ERROR_OUT_OF_MEMORY:
+ {
+ return "out of memory";
+ }
+ case TTS_ERROR_OPERATION_FAILED:
+ {
+ return "oper failed";
+ }
+ case TTS_ERROR_INVALID_STATE:
+ {
+ return "inv state";
+ }
+ default:
+ {
+ return "uknown error";
+ }
+ }
}
static char * get_tts_state( tts_state_e r )
{
- switch( r )
- {
- case TTS_STATE_CREATED:
- {
- return "created";
- }
- case TTS_STATE_READY:
- {
- return "ready";
- }
- case TTS_STATE_PLAYING:
- {
- return "playing";
- }
- case TTS_STATE_PAUSED:
- {
- return "pause";
- }
- default:
- {
- return "uknown state";
- }
- }
+ switch( r )
+ {
+ case TTS_STATE_CREATED:
+ {
+ return "created";
+ }
+ case TTS_STATE_READY:
+ {
+ return "ready";
+ }
+ case TTS_STATE_PLAYING:
+ {
+ return "playing";
+ }
+ case TTS_STATE_PAUSED:
+ {
+ return "pause";
+ }
+ default:
+ {
+ return "uknown state";
+ }
+ }
}
-// -------------------------------------------------------------------------------------------------
+//-------------------------------------------------------------------------------------------------
bool get_supported_voices_cb(tts_h tts, const char* language, int voice_type, void* user_data)
{
- DEBUG("LANG: %s; TYPE: %d", language, voice_type);
+ DEBUG("LANG: %s; TYPE: %d", language, voice_type);
- Service_Data *sd = user_data;
- Voice_Info *vi = calloc(1, sizeof(Voice_Info));
+ Service_Data *sd = user_data;
+ Voice_Info *vi = calloc(1, sizeof(Voice_Info));
- int len = strlen(language);
+ if(asprintf(&vi->language, "%s",language) < 0)
+ {
+ ERROR(MEMORY_ERROR);
+ return ECORE_CALLBACK_CANCEL;
+ }
- vi->language = calloc(len + 1, sizeof(char));
- strcpy(vi->language, language);
+ vi->voice_type = voice_type;
- vi->voice_type = voice_type;
+ sd->available_languages = eina_list_append(sd->available_languages, vi);
- sd->available_languages = eina_list_append(sd->available_languages, vi);
-
- return ECORE_CALLBACK_RENEW;
+ return ECORE_CALLBACK_RENEW;
}
static void __tts_test_utt_started_cb(tts_h tts, int utt_id, void* user_data)
{
- DEBUG("Utterance started : utt id(%d) \n", utt_id);
-
- return;
+ DEBUG("Utterance started : utt id(%d) \n", utt_id);
+ return;
}
static void __tts_test_utt_completed_cb(tts_h tts, int utt_id, void* user_data)
{
- DEBUG("Utterance completed : utt id(%d) \n", utt_id);
-
- return;
+ DEBUG("Utterance completed : utt id(%d) \n", utt_id);
+ if(last_utt_id - utt_id > FLUSH_LIMIT)
+ flush_flag = EINA_TRUE;
+ else
+ {
+ if(flush_flag)
+ flush_flag = EINA_FALSE;
+ }
+ return;
}
bool tts_init(void *data)
{
- DEBUG( "--------------------- TTS_init START ---------------------");
- Service_Data *sd = data;
+ DEBUG( "--------------------- TTS_init START ---------------------");
+ Service_Data *sd = data;
+
+ int r = tts_create( &sd->tts );
+ DEBUG( "Create tts %d (%s)", r, get_tts_error( r ) );
- int r = tts_create( &sd->tts );
- DEBUG( "Create tts %d (%s)", r, get_tts_error( r ) );
+ r = tts_set_mode( sd->tts, TTS_MODE_DEFAULT );
+ DEBUG( "Set tts mode SR %d (%s)", r, get_tts_error( r ) );
- r = tts_set_mode( sd->tts, TTS_MODE_DEFAULT );
- DEBUG( "Set tts mode SR %d (%s)", r, get_tts_error( r ) );
+ r = tts_prepare( sd->tts );
+ DEBUG( "Prepare tts %d (%s)", r, get_tts_error( r ) );
- r = tts_prepare( sd->tts );
- DEBUG( "Prepare tts %d (%s)", r, get_tts_error( r ) );
+ tts_set_state_changed_cb(sd->tts, state_changed_cb, sd);
- tts_set_state_changed_cb(sd->tts, state_changed_cb, sd);
+ tts_set_utterance_started_cb(sd->tts, __tts_test_utt_started_cb, sd);
+ tts_set_utterance_completed_cb( sd->tts, __tts_test_utt_completed_cb, sd);
- tts_set_utterance_started_cb(sd->tts, __tts_test_utt_started_cb, sd);
- tts_set_utterance_completed_cb( sd->tts, __tts_test_utt_completed_cb, sd);
+ DEBUG( "---------------------- TTS_init END ----------------------\n\n");
+ return true;
+}
- DEBUG( "---------------------- TTS_init END ----------------------\n\n");
- return true;
+Eina_Bool tts_pause_set(Eina_Bool pause_switch)
+{
+ Service_Data *sd = get_pointer_to_service_data_struct();
+ if(!sd)
+ return EINA_FALSE;
+
+ if(pause_switch)
+ {
+ if(!tts_pause(sd->tts))
+ pause_state = EINA_TRUE;
+ else
+ return EINA_FALSE;
+ }
+ else if(!pause_switch)
+ {
+ if(!tts_play(sd->tts))
+ pause_state = EINA_FALSE;
+ else
+ return EINA_FALSE;
+ }
+ return EINA_TRUE;
}
-Eina_Bool tts_speak( void * data )
+Eina_Bool tts_speak(char *text_to_speak, Eina_Bool flush_switch)
{
- Service_Data *sd = data;
- int speak_id;
- const char * text_to_speak = NULL;
+ Service_Data *sd = get_pointer_to_service_data_struct();
+ int speak_id;
- if (sd->_dbus_txt_readed == 0 && sd->text_from_dbus ) {
- text_to_speak = sd->text_from_dbus;
- sd->_dbus_txt_readed = 1;
- }
- else
- text_to_speak = sd->text_to_say_text;
+ if(!sd)
+ return EINA_FALSE;
- DEBUG( "tts_speak\n");
- DEBUG( "text to say:%s\n", text_to_speak);
- if ( !text_to_speak ) return EINA_FALSE;
- if ( !text_to_speak[0] ) return EINA_FALSE;
+ if(flush_flag || flush_switch)
+ tts_stop(sd->tts);
- tts_add_text( sd->tts, text_to_speak, NULL, TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &speak_id );
- DEBUG("added id to:%d\n", speak_id);
+ DEBUG( "tts_speak\n");
+ DEBUG( "text to say:%s\n", text_to_speak);
+ if ( !text_to_speak ) return EINA_FALSE;
+ if ( !text_to_speak[0] ) return EINA_FALSE;
- tts_play( sd->tts );
- return EINA_FALSE;
+ if(tts_add_text( sd->tts, text_to_speak, sd->language, TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &speak_id))
+ return EINA_FALSE;
-}
+ DEBUG("added id to:%d\n", speak_id);
+ last_utt_id = speak_id;
-bool update_supported_voices(void *data)
-{
- DEBUG("START");
- tts_state_e state;
-
- Service_Data *sd = data;
-
- int res = tts_get_state(sd->tts, &state);
-
- if(res != TTS_ERROR_NONE)
- {
- DEBUG("CANNOT RETRIVE STATE");
- return false;
- }
-
- if(state == TTS_STATE_READY)
- {
- tts_foreach_supported_voices(sd->tts, get_supported_voices_cb, sd);
- }
- else
- {
- sd->update_language_list = true;
- }
-
- DEBUG("END")
- return true;
+ return EINA_TRUE;
}
-void state_changed_cb(tts_h tts, tts_state_e previous, tts_state_e current, void* user_data)
+Eina_Bool update_supported_voices(void *data)
{
- DEBUG("++++++++++++++++state_changed_cb\n++++++++++++++++++");
- DEBUG("current state:%s and previous state:%s\n", get_tts_state(current), get_tts_state(previous));
- Service_Data *sd = user_data;
-
- if(current == TTS_STATE_READY) {
- DEBUG("State is ready after prepare\n");
- tts_speak(sd);
- }
+ DEBUG("START");
+ tts_state_e state;
+
+ Service_Data *sd = data;
+
+ int res = tts_get_state(sd->tts, &state);
+
+ if(res != TTS_ERROR_NONE)
+ {
+ DEBUG("CANNOT RETRIVE STATE");
+ return EINA_FALSE;
+ }
+
+ if(state == TTS_STATE_READY)
+ {
+ tts_foreach_supported_voices(sd->tts, get_supported_voices_cb, sd);
+ }
else
- {
- DEBUG("State is diffrent then ready after prepare!\n");
- }
-}
+ {
+ sd->update_language_list = EINA_TRUE;
+ }
-void spi_prepare_text(void *data)
-{
- Service_Data *sd = data;
- sd->say_text = true;
- sd->update_language_list = false;
- DEBUG("PREPARE TEXT!!!!!!!!!!!!!!\n");
-
- tts_stop(sd->tts);
- tts_append_text(sd);
+ DEBUG("END")
+ return EINA_TRUE;
}
-void tts_append_text(void *data)
+void state_changed_cb(tts_h tts, tts_state_e previous, tts_state_e current, void* user_data)
{
- Service_Data *sd = data;
- tts_state_e state;
- tts_get_state(sd->tts, &state);
-
- DEBUG("text append:::!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
- if(state == TTS_STATE_READY)
- {
- DEBUG("TTS state == ready!\n");
- tts_speak(data);
- }
+ if(pause_state)
+ {
+ DEBUG("TTS is currently paused. Resume to start reading");
+ return;
+ }
+
+ DEBUG("++++++++++++++++state_changed_cb\n++++++++++++++++++");
+ DEBUG("current state:%s and previous state:%s\n", get_tts_state(current), get_tts_state(previous));
+ Service_Data *sd = user_data;
+
+ if(current == TTS_STATE_READY || current == TTS_STATE_PAUSED)
+ {
+ DEBUG("TTS state == %s!", get_tts_state(current));
+ tts_play(sd->tts);
+ }
else
- {
- DEBUG("TTS state != ready!\n");
- }
+ {
+ DEBUG("TTS state != ready or paused!\n");
+ }
}
void spi_stop( void *data)
{
- Service_Data *sd = data;
- sd->say_text = false;
- sd->update_language_list = false;
- free(sd->text_to_say_text);
- free(sd->description_text);
- free((char*)sd->text_from_dbus);
- free(sd->current_value);
- sd->text_to_say_text = NULL;
- sd->description_text = NULL;
- sd->text_from_dbus = NULL;
- sd->current_value = NULL;
- tts_stop(sd->tts);
-}
+ Service_Data *sd = data;
+ sd->update_language_list = false;
+ free((char*)sd->text_from_dbus);
+ free(sd->current_value);
+ sd->text_from_dbus = NULL;
+ sd->current_value = NULL;
+ tts_stop(sd->tts);
+}
\ No newline at end of file
/*
- * screen_reader_xml.c
- *
- * Created on: Mar 26, 2014
- * Author: m.skorupinsk
- */
+* screen_reader_xml.c
+*
+* Created on: Mar 26, 2014
+* Author: m.skorupinsk
+*/
+
+#define _GNU_SOURCE
+
#include <stdio.h>
#include "logger.h"
+#include "xml_parser.h"
#include "screen_reader_xml.h"
static Service_Data *service_data;
char *get_text_to_read(const char *action, AtspiAccessible *widget)
{
- char *description = service_data->description_text;
-
- DEBUG("DESCRIPTION %s\n", description);
-
- if(description == NULL)
- {
- DEBUG("NULL DESCRIPTION\n");
- return NULL;
- }
- else if(description[0] == 0)
- {
- DEBUG("DESCRIPTION[0] = 0\n");
- return NULL;
- }
-
- int level = service_data->information_level;
-
- Eina_Simple_XML_Attribute *attributes[2] = {NULL, NULL};
-
- char level_str[2];
- snprintf(level_str, 2, "%d", level);
-
- DEBUG("THE LEVEL STRING: %s LEVEL: %d\n", level_str, level);
-
- attributes[0] = eina_simple_xml_attribute_new(NULL, "level", level_str);
-
- char *ret_str;
- char *tmp = get_string_str(NULL, description, attributes, "Information_Level");
- eina_simple_xml_attribute_free(attributes[0]);
-
- AtspiStateSet *state_set = atspi_accessible_get_state_set (widget);
- AtspiStateType state = ATSPI_STATE_ENABLED;
- gboolean bstate = atspi_state_set_contains(state_set, state);
-
- g_object_unref(state_set);
-
- if(!bstate)
- {
- const char *string_is_disable = "is disabled";
- GError *err = NULL;
- int ret_str_size;
- int cnt;
-
- ret_str_size = strlen(tmp) + strlen(string_is_disable) + 1;/* offset for spaces */
- ret_str = malloc(ret_str_size);
- if(!ret_str)
- {
- ERROR("Failed to allocate memory");
- free(tmp);
- return NULL;
- }
- /* example push_button BLUE is disabled */
- cnt = snprintf(ret_str, ret_str_size, "%s %s", tmp, string_is_disable);
- free(tmp);
- if (cnt < ret_str_size)/* Buffer should be of expected size and this also checks for -1 error */
- {
- ERROR("Failed to format buffer...");
- ERROR("Buffer[%d/%d][%s]", cnt, ret_str_size, ret_str);
- free(ret_str);
- return NULL;
- }
- }
- else
- ret_str = tmp;
-
- DEBUG("\n\n-> -> -> THE STRING TO SAY: <- <- <- \n%s\n\n", ret_str);
-
- return ret_str;
+ char *description = NULL;
+
+ DEBUG("DESCRIPTION %s\n", description);
+
+ if(description == NULL)
+ {
+ DEBUG("NULL DESCRIPTION\n");
+ return NULL;
+ }
+ else if(description[0] == 0)
+ {
+ DEBUG("DESCRIPTION[0] = 0\n");
+ return NULL;
+ }
+
+ int level = service_data->information_level;
+
+ Eina_Simple_XML_Attribute *attributes[2] = {NULL, NULL};
+
+ char *level_str;
+ if(asprintf(&level_str, "%d", level) < 0)
+ {
+ ERROR("Failed to allocate memory...");
+ return NULL;
+ }
+
+ DEBUG("THE LEVEL STRING: %s LEVEL: %d\n", level_str, level);
+
+ attributes[0] = eina_simple_xml_attribute_new(NULL, "level", level_str);
+ free(level_str);
+
+ char *ret_str;
+ char *tmp = get_string_str(NULL, description, attributes, "Information_Level");
+ eina_simple_xml_attribute_free(attributes[0]);
+
+ AtspiStateSet *state_set = atspi_accessible_get_state_set (widget);
+ AtspiStateType state = ATSPI_STATE_ENABLED;
+ gboolean bstate = atspi_state_set_contains(state_set, state);
+
+ g_object_unref(state_set);
+
+ if(!bstate)
+ {
+ const char *string_is_disable = "is disabled";
+ /* example push_button BLUE is disabled */
+ if(asprintf(&ret_str, "%s %s", tmp, string_is_disable) < 0)
+ {
+ ERROR("Failed to allocate memory");
+ free(tmp);
+ return NULL;
+ }
+ }
+ else
+ ret_str = tmp;
+
+ DEBUG("\n\n-> -> -> THE STRING TO SAY: <- <- <- \n%s\n\n", ret_str);
+ free(tmp);
+ return ret_str;
}
void xml_init(Service_Data *sd)
{
- service_data = sd;
+ service_data = sd;
}
--- /dev/null
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <atspi/atspi.h>
+#include <tone_player.h>
+#include "logger.h"
+#include "screen_reader_tts.h"
+#include "smart_notification.h"
+
+#define RED "\x1B[31m"
+#define RESET "\033[0m"
+
+#define ITEMS_NOTIFICATION "Visible items from %d to %d"
+
+static Eina_Bool status = EINA_FALSE;
+
+static void _smart_notification_focus_chain_end(void);
+static void _smart_notification_realized_items(int start_idx, int end_idx);
+
+/**
+ * @brief Smart Notifications event handler
+ *
+ * @param nt Notification event type
+ * @param start_index int first visible items index smart_notification_realized_items
+ * @param end_index int last visible items index used for smart_notification_realized_items
+ */
+void smart_notification(Notification_Type nt, int start_index, int end_index)
+{
+ if(!status)
+ return;
+
+ switch(nt)
+ {
+ case FOCUS_CHAIN_END_NOTIFICATION_EVENT:
+ _smart_notification_focus_chain_end();
+ break;
+ case REALIZED_ITEMS_NOTIFICATION_EVENT:
+ _smart_notification_realized_items(start_index, end_index);
+ break;
+ default:
+ DEBUG("Gesture type %d not handled in switch", nt);
+ }
+}
+
+/**
+ * @brief Used for getting first and last index of visible items
+ *
+ * @param scrollable_object AtspiAccessible object on which scroll was triggered
+ * @param start_index int first visible items index smart_notification_realized_items
+ * @param end_index int last visible items index used for smart_notification_realized_items
+ */
+void get_realized_items_count(AtspiAccessible *scrollable_object, int *start_idx, int *end_idx)
+{
+ int count_child, jdx;
+ AtspiAccessible *child_iter;
+ AtspiStateType state = ATSPI_STATE_SHOWING;
+
+ if(!scrollable_object)
+ {
+ DEBUG("No scrollable object");
+ return;
+ }
+
+ count_child = atspi_accessible_get_child_count(scrollable_object, NULL);
+
+ for(jdx = 0; jdx < count_child; jdx++)
+ {
+ child_iter = atspi_accessible_get_child_at_index(scrollable_object, jdx, NULL);
+
+ AtspiStateSet* state_set = atspi_accessible_get_state_set(child_iter);
+
+ gboolean is_visible = atspi_state_set_contains(state_set, state);
+ if(is_visible)
+ {
+ *start_idx = jdx;
+ DEBUG("Item with index %d is visible", jdx);
+ }
+ else
+ DEBUG("Item with index %d is NOT visible", jdx);
+ }
+ *end_idx = *start_idx + 8;
+}
+
+/**
+ * @brief Scroll-start/Scroll-end event callback
+ *
+ * @param event AtspiEvent
+ * @param user_data UNUSED
+ */
+static void
+_scroll_event_cb(const AtspiEvent *event, gpointer user_data)
+{
+ if(!status)
+ return;
+
+ int start_index, end_index;
+ start_index = 0;
+ end_index = 0;
+
+ fprintf(stderr, "Event: %s: %d, obj: %p: role: %s\n", event->type, event->detail1, event->source,
+ atspi_accessible_get_role_name(event->source, NULL));
+
+ if (!strcmp(event->type, "object:scroll-start"))
+ {
+ DEBUG("Scrolling started");
+ tts_speak("Scrolling started", EINA_TRUE);
+ }
+ else if (!strcmp(event->type, "object:scroll-end"))
+ {
+ DEBUG("Scrolling finished");
+ tts_speak("Scrolling finished", EINA_FALSE);
+ get_realized_items_count((AtspiAccessible *)event->source, &start_index, &end_index);
+ _smart_notification_realized_items(start_index, end_index);
+ }
+}
+
+/**
+ * @brief Initializer for smart notifications
+ *
+ *
+ */
+void smart_notification_init(void)
+{
+ DEBUG("Smart Notification init!");
+
+ AtspiEventListener *listener;
+
+ listener = atspi_event_listener_new(_scroll_event_cb, NULL, NULL);
+ atspi_event_listener_register(listener, "object:scroll-start", NULL);
+ atspi_event_listener_register(listener, "object:scroll-end", NULL);
+
+ haptic_module_init();
+
+ status = EINA_TRUE;
+}
+
+/**
+ * @brief Smart notifications shutdown
+ *
+ */
+void smart_notification_shutdown(void)
+{
+ status = EINA_FALSE;
+}
+
+/**
+ * @brief Smart notifications focus chain event handler
+ *
+ */
+static void _smart_notification_focus_chain_end(void)
+{
+ if(!status)
+ return;
+
+ DEBUG(RED"Smart notification - FOCUS CHAIN END"RESET);
+
+ tone_player_stop(0);
+ tone_player_start(TONE_TYPE_SUP_CONFIRM, SOUND_TYPE_MEDIA, 200, NULL);
+}
+
+/**
+ * @brief Smart notifications realized items event handler
+ *
+ */
+static void _smart_notification_realized_items(int start_idx, int end_idx)
+{
+ if(!status)
+ return;
+
+ if(start_idx == end_idx)
+ return;
+
+ DEBUG(RED"Smart notification - Visible items notification"RESET);
+
+ char buf[256];
+
+ sprintf(buf, ITEMS_NOTIFICATION, start_idx, end_idx);
+
+ tts_speak(strdup(buf), EINA_FALSE);
+}