Building a better screen reader for the Linux desktop, one step at a time.

Related tags

Miscellaneous odilia
Overview

Odilia Screen Reader

Welcome to Odilia!

Accessibility on Linux has historically been under-developed, under-maintained, and therefore not up to modern standards for many blind people. We're hear to help with that!

Odilia is a new screen reader for the Linux desktop. It's written in Rust, for maximum performance and stability.

Status: Alpha

This is absolutely not stable or production ready in any way! Everything is in a very early stage and we're breaking things on a daily basis!

Building

To build odilia:

git clone https://github.com/odilia-app/odilia
cd odilia
cargo build --release
# At this point the compiled program is at ./target/release/odilia
# Optionally, run this to install Odilia to ~/.cargo/bin:
cargo install --path .
./setup-permissions.sh

Udev Permissions

Odilia uses the Linux kernel's evdev interface to listen for and redirect events from input devices, such as your keyboard and mouse.

Evdev is normally a privileged interface, since any application that can access it could use it for malicious purposes, for example, creating a keylogger. For this reason, to run Odilia, you must give yourself access to evdev. This can be done by running the setup-permissions.sh shell script included with Odilia. The script adds some udev rules, then creates an odilia group. Any users added to this group and the input group will be able to run Odilia.

Contributing

This is a very young project, we appreciate any and all contributions! However, please be aware there is a very llarge learning curve to helping with this project, particularly due to the lack of documentation, or complete documentation, of many of the libraries and technologies that comprise the Linux accessibility stack. For this reason, we are currently focused on learning as much as we can, and writing code to take advantage of it, and we don't have lots of time to mentor new contributors or review pull requests.

Once the ground-work has been layed, accepting contributions should get much easier. We are greatful for your cooperation in this regard!

License

All our code is licensed under the GPL v3.

Comments
  • Unable to run on up to date Arch/no speech

    Unable to run on up to date Arch/no speech

    I am running the latest Arch Linux, with every single update. Running the AUR build gives me several errors

    1. It does not move the config.toml into the .config/odilia directory
    2. Moving that file into the correct place results in Odilia starting, with no speech and a flood of debug events handled withhout error events
    3. Building from source and running the setup permissions script installs, and works fine however, Odilia has zero speech at all, as well as the aforementioned errors I have run with Xorg and Sway, with zero luck running Odilia at all, it is acting as if speech-dispatcher is not picking up Odilia, despite it starting up fine, connecting with speech-dispatcher.

    I figured maybe Orca was causing that so I pkilled Orca, with no luck at all. Odilia refuses to speak at all.

    Things I've tried

    Install from AUR, and remove,then remove the cache and start over Manually create the config file in .config/Odilia Build from source and run from both a hand made .desktop file, as well as a terminal with no luck

    All I can do is ctrl+C Odilia from a terminal

    bug enhancement Core TTS 
    opened by celtichawk 14
  • Fail to build on Ubuntu 22.04

    Fail to build on Ubuntu 22.04

    I get following error when build on Ubuntu 22.04:

    $ cargo build --release
    error: failed to parse manifest at `/home/hgneng/code/odilia/Cargo.toml`
    
    Caused by:
      feature `strip` is required
    
      The package requires the Cargo feature called `strip`, but that feature is not stabilized in this version of Cargo (1.57.0).
      Consider adding `cargo-features = ["strip"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.
      See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-strip-option for more information about the status of this feature.
    $ cargo --version
    cargo 1.57.0
    

    After adding cargo-features = ["strip"] to the top of Cargo.toml, I get following error:

    $ cargo build --release
        Updating crates.io index
    error: failed to select a version for the requirement `zbus = "^3.0.0"`
    candidate versions found which didn't match: 2.3.2, 2.3.1, 2.3.0, ...
    location searched: crates.io index
    required by package `odilia v0.0.1 (/home/hgneng/code/odilia/odilia)`
    

    Will upgrading rust/cargo fix the build errors? What should I do?

    bug Bin 
    opened by hgneng 14
  • Consider Relicensing `atspi`

    Consider Relicensing `atspi`

    Currently, @DataTriny is working on using our atspi crate for the AccessKit suite of tools. These tools are licensed under Apache 2.0, MIT, and BSD licenses, which are incompatible with the GPL (in that direction).

    Although we currently license atspi with the LGPL, this is somewhat problematic with Rust, where you don't link libraries together like you do in C. I wish there was a license similar to the LGPL for Rust, but there really isn't.

    So I propose three options:

    • Keep it the same. This could restrict usage, but from the GNU standpoint, that's a good thing.
    • Relicense under the MPL, a file-based copy-left license. So technically they could add files to add functionality without sharing changes, but realistically that's probably not going to happen.
    • Relicense as the Rust-standard MIT or Apache 2.0; this would allow the crate to be used in propietary products with modifications. The upside is thst it will massively increase adoption since it can be used in a project with any license. So does MPL, but since it's not as popular, it may scare some off even though that has the benefit of sharing modifications.

    I'm not going to give my own opinion here for now, just want to see what others think. We'll probably need consent from everyone involved to relicense, so I'll have to see what @mcb2003 thinks as well. We never really talked about how to license individual, separate components, and Rust complicates things with its package management.

    Thoughts?

    opened by TTWNO 7
  • Org contributions

    Org contributions

    Odilia looks like a very interesting project! Although I'm not a visually impaired linux user, I would like to help out as I believe that accessibility is a huge gap that we need to bridge in our community.

    If anyone could point me to a todo list, I'd love to try and contribute.

    Sincerely, Aakash Sen Sharma

    opened by Shinyzenith 7
  • Qt Applications Do NOT Work

    Qt Applications Do NOT Work

    According to the following comment, the Event.xml file in the atspi library is not correct.

    Because of this, Odilia can currently only receive events from GTK applications; Qt applications use a different event signature which errors out the zbus crate with "Invalid signature" errors.

    This is not a bug in DBus, Odilia, GTK or Qt. atspi is currently allowing multiple signature types for events; this needs to be standardized at the library level, and we should be happy to help. I personally know nothing of GTK, Qt, or DBus code itself, but if atspi needs some fixing, I'm sure either I or @mcb2003 should be able to take a gander.

    Once this is stabilized library-side, Odilia should immediately work with Qt applications, with no further modifications necessary. :+1:

    bug at-spi 
    opened by TTWNO 6
  • atspi: `Accessible::get_state` won't work

    atspi: `Accessible::get_state` won't work

    The current implementation of Accessible::get_state can't work because the return type is more complex than the signature implies.

    AT-SPI state set is an 8 bytes bitflag that is splitted in half and passed as a two-element 32-bit integers array through D-Bus.

    I have a working implementation of this data structure on my AccessKit AT-SPI adapter branch. I would happily add it here but it currently requires two dependencies new to this project:

    • enumflags2: for representing the bitflag,
    • strum: to convert a state into its string representation for raising state changed events.

    Of course, strum isn't really needed if you only care about the client side of AT-SPI, and even on the server-side you could still write the strings manually, but this is inconvenient. So that's why I don't directly open a PR here.

    What do you guys think? Is it OK to bring these two dependencies? Would you prefer having a strum feature flag? Are you even interested in having the atspi crate useful for building AT-SPI providers?

    opened by DataTriny 5
  • Wireless Devices are Disconnected When Running Odilia

    Wireless Devices are Disconnected When Running Odilia

    When Odilia is started, both my wifi adapter and my bluetooth adapter get disconnected from any devices / networks they're connected to.

    As of yet, I'm unsure of why this is, although I'm thinking it might be related to #19.

    bug help wanted Core 
    opened by mcb2003 5
  • [`sohkd`]: Kills Wi-Fi and Bluetooth

    [`sohkd`]: Kills Wi-Fi and Bluetooth

    I suspect evdev is causing some kind of issue and killing all Wi-Fi and BT connections. Whatever it's doing, it seems to cause rfkill to activate on both my wlan and bluetooth interfaces. I need to manually rfkill unblock wlan to get back wifi after enabling the daemon.

    Interestingly, this does not happen with swhkd, which sohkd is based on. I suspect it may have something to do with the version of evdev each project is using, since Odilia's hotkey daemon has been using the newest, 0.12.0 version, while swhkd has been using 0.11.x; perhaps there is an upstream bug to be submitted to evdev.

    Further investigation necessary.

    bug help wanted Input 
    opened by TTWNO 4
  • [atspi][clippy] fixes (some) clippy noise

    [atspi][clippy] fixes (some) clippy noise

    Fix match on bool and fix an unneeded reference. Fix cast from i32 to usize using 'try_from' - breaks AccessibleExts signatures. Guidance needed! Silence Clippy on missing backticks in documentation. Not sure whether the backticks are appropriate here.

    opened by luukvanderduim 4
  • atspi: Make `EventBody` generic over serializable types for `kind`

    atspi: Make `EventBody` generic over serializable types for `kind`

    I still haven't figured out the best way forward for this, but at least now it's possible to serialize events holding a kind which type is something other than &str. At least I'll be able to take advantage of this for AccessKit.

    • Added serde support to the State type.
    • Rearranged EventBodyQT (I don't see why we would need a borrowing version of this type, it's kind of a bug in Qt so you wouldn't want anybody to use it on the server-side).
    • Updated signals to use EventBody<&str> (except object's state_changed which now takes EventBody<State>).

    Hopefully this can spark ideas on how to better type-check these event related structs.

    opened by DataTriny 4
  • Pair down logging systems

    Pair down logging systems

    Currently two logging systems are used across the various binaries and libraries for the project.

    sohkd and sohks use the log crate, and the rest of Odilia is using tracing. Pick one and make the rest conform. I'm happy with either as they seem to work nearly the same, but I don't know enough about what matters to make a choice. They both work around the same for me.

    good first issue Core 
    opened by TTWNO 4
  • Make a

    Make a "higher-level" SSIP library.

    The currently ssip-cleint library is sufficient to handle all communication with speech-dispatcher, however, I'm somewhat concerned that there are a lot of "weird" things about it that won't make sense unless you're familiar with the protocol. For example: If you want to send speech, you must await the return value, or when you send next, speech-dispatcher will have issues, you need to use SendLines(Vec) instead of SendLine(String), unless you want to add your own final "." line to end the wrong.

    There should be a less obtuse way to communicate with speech-dispatcher. I'm proposing something like ssip or speechd (on crates.io).

    This library will have functions (async and non-async) to communicate with speech-dispatcher, and commands like "cancel", "stop", or "quit" will jump the lin in the internal queue.

    Not sure exactly how we'll implement all of this, but let's put some ideas in here.

    enhancement help wanted TTS 
    opened by TTWNO 0
  • [tts]: speech-dispatcher Requires Wait (500ms) Before Usage After Spwn

    [tts]: speech-dispatcher Requires Wait (500ms) Before Usage After Spwn

    When connecting to speech-dispatcher, it's nice if we can use the auto-spawning functionality. Unfortunately, it's somewhat annoying to use for two reasons:

    1. It fails to speak in a new process after it's been awoken. For example, if one were to use autospawn to start speech-dispatcher, then stop Odilia and start it again quickly, then speech-dispatcher will refuse to speak. I can't tell if that's a speech-dispatcher problem or a pulseaudio problem. Who knows.
    2. When you auto-spawn, you need to wait around 500ms because: "Due to a bug in Speech Dispatcher, it is currently necessary to include a wait statement after the autospawn for about 0.5 seconds before attempting a connection."

    We should submit these bugs upstream and see if we can help fix them.

    opened by TTWNO 0
  • Additional Speech Stoppers

    Additional Speech Stoppers

    As Cameron points out in their issue, Odilia only stops speech when the control key is pressed. Obviously, there are a few other cases where speech may want to be interrupted.

    For example:

    1. Switching applications.
    2. Typing a letter.

    For 1) it should be fairly easy to do if the default SpeechDispatcher priority can be set to allow interruption. For 2) I'm not sure how to do this without pretty extensive overhauls to our fork of swhkd.

    bug help wanted Input 
    opened by TTWNO 0
  • AUR Package Out Of Date

    AUR Package Out Of Date

    Our AUR package reflects the initial, yggdrasil-prototype architecture of a single executable. Now we need two separate systems to handle at-spi events as well as keyboard/user input. In addition, I think the git repo has changed as well.

    Basically, a very large overhaul will be necessary. Just putting this here so it's catalogued.

    good first issue Core Bin 
    opened by TTWNO 0
  • Speech Abstraction Layer

    Speech Abstraction Layer

    after a thread on the audiogames.net forum regarding speech dispatcher not working, therefore user is left without a way to use their computer in graphical mode, I concluded that, regardless how good speech dispatcher may be from a unix philosophi standpoint, it's made of many moving parts, two many imho, any of which can bring the entire system down, simply by failing. In a world where speech is the only way for visually impaired people to use a computer therefore as critical as the GPU for sighted users, having it fail on us is simply inacceptable. Dear readers with some kind of sight, would you like your screen to go black simply because the shader cache was full for example? Also, graphics are integrated everywhere in the stack while speech isn't, but that's another discussion for another time. So then, as I'm sure you won't like that, why should we have to deal with it? I took this idea from screenreaders like nvda and fenrir for the tty, where there's a speech abstraction inside the sr itself, not speech dispatcher. Then, there are different backends facilitating speech, which eventually perhaps give back pcm wave data to the sr, which gets processed by some internal systems, for example direct interaction with pipewire. So, in this case, we would use a rust trait to abstract away the concrete implementation of the backend speech provider, then probably the sr would use Box<dyn SpeechProvider> as the interface through which to deliver speech to the user. For now, this is the draft I want to propose for this, feel free to modify it and suggest improvements, as this one is probably here to stay after it'll be implemented

    pub trait SpeechProvider: Sized {
        type Configurator;
        type Error;
    type Buffer;
        fn init_speaker(cfg: Self::Configurator) -> Result<Self, Self::Error>;
        fn speak<T>(&self, text: T) -> Result<Self::Buffer, Self::Error>
        where
            T: AsRef<str>;
        fn pause(&self) -> Result<(), Self::Error>;
        fn stop(&self) -> Result<(), Self::Error>;
        //configuration specific methods like set_volume, get_volume, set_pitch, etc  are not required because the configurator is backend specific and will load values in the init method, this is ment to be called each time the configuration is supposed to change.
        fn reload_configuration(self, cfg: Self::Configurator) -> Result<Self, Self::Error>;
    }
    
    

    For now, here are a few things the current implementation doesn't explain:

    • [ ] loading the right speech provider based on configuration and populating the middleware with it. Define mechanism that would fit inside rust's typesystem, such as enum dispatch and dynamic dispatch
      • [ ] loading the right provider specific configuration
        • where is that located?
        • should it be standardised, or anywhere the config crate can find it?
        • how are changes to it tracked?
        • do we allow implementations to define their own format, or do we inforce toml everywhere?
    • [ ] buffer handling
      • do we introduce synthizer now?
      • how do we pass the buffer over? rust isn't a dynamically typed language, so how do we interract with the buffer type? Is an associated type even a good mechanism, given what we want to do?
        • as to the functionality of the buffer itself, do we treat it like a vec, or do we make an additional buffer trait that has a method which returns an iterator of float values?
      • or maybe we should implement pipewire access directly
      • do we allow custom sample rates, or define a static one?
    enhancement help wanted 
    opened by albertotirla 10
  • Safety & Simplicity for Config Files

    Safety & Simplicity for Config Files

    At this time, Rust's type system is not being used to verify (before the program starts) that the configuration file is correct. Error with the JSON are far too common, and kind of hard to diagnose.

    This issue contains two jobs:

    1. Simplify the config file to allow the use of non-JSON strings as Odilia events. Currently each event is fairly long due to the verbosity of JSON. -- Simplicity
    2. Verify during the initialization process (before grabbing input devices) that the config file is correct and that all the keybindings will be sent properly through the socket. -- Safety

    This is boring work, but should be fairly easy for a beginner to figure out, so I will label it as good first issue.

    enhancement good first issue help wanted Input 
    opened by TTWNO 0
Owner
Odilia
Building a better screen reader for the Linux desktop, one step at a time.
Odilia
Shows my Spotify status on a small screen. Powered by ESP-IDF & built with 🧡 in Rust! 🦀

ESP Display A small embedded project that shows what I'm listening to on Spotify by using my Spotify service. Example Notable Features ESP32-S3 board

Isaiah Gamble 3 Apr 10, 2024
`fugit` provides a comprehensive library of `Duration` and `Instant` for the handling of time in embedded systems, doing all it can at compile time.

fugit fugit provides a comprehensive library of Duration and Instant for the handling of time in embedded systems, doing all it can at compile time. T

Emil Fresk 40 Oct 2, 2022
A programming language. Better mantra pending.

Dusk Dusk is a programming language I've been working on on and off for the past while now. It's still very much in its infancy (... a quick look thro

Kaylynn Morgan 14 Oct 24, 2022
A better message queue built by rust

bettermq A better message queue built by rust I start this project to study Rust

Sun Junyi 13 Dec 16, 2022
A simply better way to make Discord bots.

Cognite ?? A simple blazingly fast language agnostic microservice driven Discord bot framework made in rust that leverages Apache Kafka and KeyDB to t

Eludris 5 Aug 26, 2022
Better Valtrun with Aimbot and Bhop🔥🔥🔥

BetterValthrun Better Valtrun with Aimbot and Bhop?????? The New Era Valthrun is an open source external Counter-Strike 2 read only kernel-level gamep

Jonas Zimmerman 8 Oct 20, 2023
The missing desktop-autotype for Bitwarden.

bitwarden-autotype The missing desktop-autotype for Bitwarden. Autotype/Autofill support has been a requested feature in Bitwarden for years, yet no p

M*C*O 26 Nov 29, 2022
A simple and fast FRC autonomous path planner (designed for swerve drive)! (Desktop/Laptop only)

This is a website developed for planning autonomous paths for FRC robots. It is intended to be a simple and fast tool to create autos, which works offline at competitions.

Weaver Goldman 2 Jan 6, 2023
One-Stop Solution for all boilerplate needs!

One Stop Solution for all boilerplate needs! Consider leaving a ⭐ if you found the project helpful. Templa-rs Templa-rs is a one-of-a-kind TUI tool wr

IEEE VIT Student Chapter 27 Aug 28, 2022
Automatically download minecraft server jars in one line

MCDL Automatically download minecraft server jars in one line (or one click) Installation Download (Windows, Linux) Install via cargo: cargo install m

Isaac Hirschfeld 1 Oct 26, 2021
RustSBI support on SiFive FU740 board; FU740 is a five-core heterogeneous processor with four SiFive U74 cores, and one SiFive S7 core

RustSBI 在 HiFive Unmatched 主板的支持软件 这个项目的目的是在SiFive HiFive Unmatched主板上支持RustSBI。 RustSBI是一个引导程序环境;主板上电时,RustSBI将会先行启动,而后,它将会找到一个可引导的操作系统,引导启动这个操作系统。 在

RustSBI 15 Dec 1, 2022
The never type (the true one!) in stable Rust.

::never-say-never The ! type. In stable Rust. Since 1.14.0. Better than an enum Never {} definition would be, since an instance of type ! automagicall

Daniel Henry-Mantilla 17 Jan 3, 2023
Notifiy when one of Elon Musk's jets flyover your own ADS-B receiver

With inpsiration from twitter/@ElonJet, this app will print notifications when one of Elon Musk's jets fly over your own ADS-B receiver ground station.

Rust ADS-B 6 Dec 19, 2022
sblade or switchblade it's a multitool in one capable of doing simple analysis with any type of data, attempting to speed up ethical hacking activities

sblade or switchblade it's a multitool in one capable of doing simple analysis with any type of data, attempting to speed up ethical hacking activities

Gabriel Correia 1 Dec 27, 2022
A simple library with just one struct which is used to wrap around pointers

A simple library with just one struct which is used to wrap around pointers. This can be used to create pointers and share them across threads without the hassle of synchronization if you really do not care about that.

null 1 Apr 11, 2022
CFD is a tool that allows you to check one or more domains to see if they are protected by CloudFlare or not.

CFD is a tool that allows you to check one or more domains to see if they are protected by CloudFlare or not. The check is carried out based on five criteria: 3 headers in the HTTP response, IP, and SSL certificate issuer. The check result can be displayed on the screen or saved to a file.

Airat Galiullin 13 Apr 7, 2023
🐀 Building a federated alternative to reddit in rust

Lemmy A link aggregator / Reddit clone for the fediverse. Join Lemmy · Documentation · Report Bug · Request Feature · Releases · Code of Conduct About

LemmyNet 7.2k Jan 3, 2023
Cassette A simple, single-future, non-blocking executor intended for building state machines.

Cassette A simple, single-future, non-blocking executor intended for building state machines. Designed to be no-std and embedded friendly. This execut

James Munns 50 Jan 2, 2023
Nimbus is a framework for building parachain consensus systems on cumulus-based parachains.

Cumulo -- Nimbus ⛈️ Nimbus is a framework for building parachain consensus systems on cumulus-based parachains. Given the regular six-second pulse-lik

null 36 Dec 14, 2022