From 2b4d06b37c9c928e8d74d8d86447d99cc8ea5796 Mon Sep 17 00:00:00 2001 From: Tait Hoyem Date: Mon, 25 Jul 2022 13:31:14 -0600 Subject: [PATCH] Initial commit --- Makefile | 7 ++ README.md | 18 ++++ speak-selection | Bin 0 -> 47432 bytes speak-selection.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 230 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100755 speak-selection create mode 100644 speak-selection.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..18d33dc --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +CC=clang +CFLAGS=-O2 -g -Wall -I/usr/include -I/usr/X11R6/include `pkg-config --cflags glib-2.0 gobject-2.0 atk-bridge-2.0 atspi-2 speech-dispatcher` +LDFLAGS=-pthread -L/usr/X11R6/lib -lm `pkg-config --libs glib-2.0 gobject-2.0 atk-bridge-2.0 atspi-2 speech-dispatcher` +EXAMPLES = $(patsubst %.c,%,$(wildcard *.c)) + +default: + $(CC) -o speak-selection $< $(CFLAGS) $(LDFLAGS) speak-selection.c diff --git a/README.md b/README.md new file mode 100644 index 0000000..89ea314 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Speak Selection (SSN) + +This program is dead simple. +While running, it wil speak out newly selected pieces of text to a user. + +It does not include any screen reading functionality. +For that, I would shamelessly recommend a project I work on called [Odilia}(https://odilia.app) +or a project I don't work on: [Orca](https://help.gnome.org/users/orca/stable/introduction.html.en). + +## Credits + +* Blatently ripped of the code from [at-spi2-examples](https://github.com/infapi00/at-spi2-examples/) + +## Requirements + +* `at-spi2-core` +* `libspeechd` +* `gcc` or `clang` diff --git a/speak-selection b/speak-selection new file mode 100755 index 0000000000000000000000000000000000000000..be4f7b30a337ea2d4c864776ac03e056e059c881 GIT binary patch literal 47432 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 p +#include +#include +#include +#include +#include + +gchar *filter_name = NULL; +SPDConnection *spd_conn = NULL; + +const static gchar* +atspi_state_get_name(gint state) +{ + GTypeClass *type_class; + GEnumValue *value; + + type_class = g_type_class_ref(ATSPI_TYPE_STATE_TYPE); + g_return_val_if_fail(G_IS_ENUM_CLASS (type_class), ""); + + value = g_enum_get_value(G_ENUM_CLASS (type_class), state); + + return value->value_nick; +} + +static gchar* +get_state_set(AtspiAccessible *accessible) +{ + AtspiStateSet *state_set = atspi_accessible_get_state_set(accessible); + GArray *states = atspi_state_set_get_states(state_set); + gchar *result = g_strdup_printf("["); + gchar *aux = NULL; + gint i; + AtspiStateType state; + + for(i = 0; i < states->len; i++) { + state = g_array_index(states, gint, i); + + aux = result; + if(i < states->len -1) + result = g_strdup_printf("%s%s,", aux, atspi_state_get_name(state)); + else + result = g_strdup_printf("%s%s", aux, atspi_state_get_name(state)); + g_free(aux); + } + + aux = result; + result = g_strconcat(aux, "]", NULL); + g_free(aux); + + g_array_free(states, TRUE); + g_object_unref(state_set); + + return result; +} + +static gchar* +get_label(AtspiAccessible *accessible) +{ + GArray *relations; + AtspiRelation *relation; + gint i; + gchar *result = ""; + + relations = atspi_accessible_get_relation_set(accessible, NULL); + if(relations == NULL) { + return ""; + } + + for(i = 0; i < relations->len; i++) { + relation = g_array_index(relations, AtspiRelation*, i); + + if(atspi_relation_get_relation_type (relation) == ATSPI_RELATION_LABELLED_BY) { + result = atspi_accessible_get_name(atspi_relation_get_target (relation, 0), NULL); + } + } + + if(relations != NULL) + g_array_free(relations, TRUE); + + return result; +} + +static void +print_info(AtspiAccessible *accessible, + gchar *app_name) +{ + AtspiText *text = atspi_accessible_get_text_iface(accessible); + gchar *name = "NULL"; + gchar *role_name = "NULL"; + gchar *state_set = NULL; + gint length_of_string; + GError **error = NULL; + + if(accessible != NULL) { + name = atspi_accessible_get_name(accessible, NULL); + if((name == NULL) || (g_strcmp0(name, "") == 0)) { + name = get_label(accessible); + if((name == NULL) || (g_strcmp0(name, "") == 0)) { + length_of_string = atspi_text_get_character_count(text, error); + name = atspi_text_get_text(text, 0, length_of_string, error); + } + } + role_name = atspi_accessible_get_role_name(accessible, NULL); + } + + state_set = get_state_set(accessible); + g_print("(%s, %s, %s, %s)\n", app_name, name, role_name, state_set); + spd_sayf(spd_conn, SPD_TEXT, "%s, %s", name, role_name); + g_free(state_set); +} + +static void +on_event(AtspiEvent *event, + void *data) +{ + AtspiAccessible *application = NULL; + gchar *app_name = NULL; + + if(event->source == NULL) + return; + + /* We only care about focus/selection gain */ + if(!event->detail1) + return; + + application = atspi_accessible_get_application(event->source, NULL); + if(application == NULL) + return; + + app_name = atspi_accessible_get_name(application, NULL); + + if((filter_name != NULL) && (g_strcmp0 (app_name, filter_name) != 0)) + goto clean; + + print_info(event->source, app_name); + +clean: + g_free(app_name); +} + +static gchar* +parse_args(int *argc, + char ***argv) +{ + GError *error = NULL; + GOptionContext *context; + static gchar *name = NULL; + static GOptionEntry entries [] = + { + {"application", 'a', 0, G_OPTION_ARG_STRING, &name, "Application name", NULL}, + {NULL,}, + }; + + context = g_option_context_new(""); + g_option_context_add_main_entries(context, entries, NULL); + if(!g_option_context_parse (context, argc, argv, &error)) + { + g_print("%s\n", error->message); + g_print("Use --help for more information.\n"); + exit(0); + } + + return name; +} + +int main(int argc, gchar **argv) +{ + AtspiEventListener *listener; + char username[64]; + + filter_name = parse_args(&argc, &argv); + if(!filter_name) { + g_print("NOTE: Application name to filter not specified. Showing " + "focus/selection changes for any application.\n"); + } + if(getlogin_r(username, 64)) { + g_print("USERNAME not found. Error.\n"); + exit(1); + } + spd_conn = spd_open("speak_selection", "main", username, SPD_MODE_SINGLE); + if(!spd_conn){ + g_print("Error establishing speech dispatcher connection. Fatal error."); + exit(1); + } + + atspi_init(); + + listener = atspi_event_listener_new(on_event, NULL, NULL); + + //atspi_event_listener_register(listener, "object:state-changed:focused", NULL); + atspi_event_listener_register(listener, "object:text-caret-moved", NULL); + + atspi_event_main(); + spd_close(spd_conn); + return 0; +}