python-clipboard-speaker

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 1ff7225be540f6ae95db481660a1c3e2dc7f9fc2
parent 379334735e84ec42a19c607ea6d1e5a2d7fd6705
Author: Yuval Langer <yuvallangerontheroad@gmail.com>
Date:   Sat, 27 Nov 2021 00:55:55 +0200

Move to Python scripts.

Diffstat:
MREADME.md | 42+++++++++++++++++++++++++++++++++++++-----
Mclipboard-speaker | 72+++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Mclipboard-speaker-kill | 16+++++++++++-----
Dclipboard-speaker-kill.py | 14--------------
Dclipboard-speaker.py | 63---------------------------------------------------------------
Cclipboard-speaker -> old-shell-version/clipboard-speaker | 0
Cclipboard-speaker-kill -> old-shell-version/clipboard-speaker-kill | 0
7 files changed, 105 insertions(+), 102 deletions(-)

diff --git a/README.md b/README.md @@ -5,17 +5,43 @@ Mark some text and let it rip. -Not a fancy curiosity but an accessibility tool for people with reading disabilities. I use it every day to read. +Not a fancy curiosity but an accessibility tool for people with reading +disabilities. I use it every day to read. -1. Select some text. -2. Press the keybinding to start `clipboard-reader`. Your computer is now speaking the stuff in the selection. -3. (optional) Press the other keybinding to start `clipboard-reader-kill` and make computer stop speaking. +It basically reads whatever you mark with your mouse cursor. ## Changelog: Have a look at the <a href="CHANGELOG.md">CHANGELOG.md</a> file. -## Installation: +## Newer Python version: + +### Installation: + +1. Install the infrastructure: + `apt install espeak-ng xsel python3` +2. Copy the two executable scripts into your home bin directory: + `cp clipboard-speaker clipboard-speaker-kill ~/bin/` +3. Add the key bindings in (if you use Gnome. If you don't, look up how to + assign scripts to keybindings in your own window manager): + `Gnome Settings → Keyboard Shortcuts → All the way down and press the + button` + +### Usage: + +1. Select some text. While the text is highlighted, +2. press the keybinding assigned to the `clipboard-reader` executable to start + the reading of the highlighted text. +3. (optional, while `clipboard-speaker` is reading the text) Select some more + text and press the keybinding that starts `clipboard-reader`. The selected + text will be added to the text buffer and will be read right after the last + bunch of text. +4. (optional) GOTO 3. +5. (optional) Press the other keybinding assigned to the `clipboard-reader-kill` + script to make your computer stop speaking and clear the text buffer. + +## Older shell version: + +### Installation: 1. Install the infrastructure: `apt install daemonize espeak-ng xsel` @@ -23,3 +49,9 @@ Have a look at the <a href="CHANGELOG.md">CHANGELOG.md</a> file. `cp clipboard-speaker clipboard-speaker-kill ~/bin/` 3. Add the key bindings in: `Gnome Settings → Keyboard Shortcuts → All the way down and press the + button` + +### Usage: + +1. Select some text. +2. Press the keybinding to start `clipboard-reader`. Your computer is now speaking the stuff in the selection. +3. (optional) Press the other keybinding to start `clipboard-reader-kill` and make computer stop speaking. diff --git a/clipboard-speaker b/clipboard-speaker @@ -1,21 +1,63 @@ -#!/bin/sh +#!/usr/bin/env python3 -clipboard_speaker_directory="$HOME/.clipboard-speaker" -lock_file_path="$clipboard_speaker_directory/lock" -pid_file_path="$clipboard_speaker_directory/pid" -fifo_path="$clipboard_speaker_directory/fifo" -speak_ng_path="$(which speak-ng)" +import os +from pathlib import Path +from subprocess import Popen, PIPE +DEFAULT_WORDS_PER_MINUTE = "175" -mkdir -p "$clipboard_speaker_directory" -mkfifo --mode=600 "$fifo_path" +CLIPBOARD_SPEAKER_PATH = Path.home() / ".clipboard-speaker" +PID_FILE_PATH = CLIPBOARD_SPEAKER_PATH / "pid" +FIFO_FILE_PATH = CLIPBOARD_SPEAKER_PATH / "fifo" -# pgrep speak-ng >/dev/null || speak-ng -f "$fifo_path" -# pgrep speak-ng >/dev/null || { -# echo $$ > "$pid_file_path" -# speak-ng -f "$fifo_path" -# } +WORDS_PER_MINUTE_PATH = CLIPBOARD_SPEAKER_PATH / "words-per-minute" -xsel -p | tr '\n' ' ' > "$fifo_path" & -daemonize -v -l "$lock_file_path" -p "$pid_file_path" "$speak_ng_path" -f "$fifo_path" +def get_words_per_minute() -> str: + if not WORDS_PER_MINUTE_PATH.exists(): + with WORDS_PER_MINUTE_PATH.open("w") as words_per_minute_file: + words_per_minute_file.write(DEFAULT_WORDS_PER_MINUTE) + return DEFAULT_WORDS_PER_MINUTE + + with WORDS_PER_MINUTE_PATH.open("r") as words_per_minute_file: + words_per_minute = words_per_minute_file.read().strip() + + return words_per_minute + + +if __name__ == "__main__": + words_per_minute = get_words_per_minute() + try: + os.mkfifo(FIFO_FILE_PATH, mode=0o600) + except FileExistsError: + pass + + # https://stackoverflow.com/questions/63132778/how-to-use-fifo-named-pipe-as-stdin-in-popen-python + fifo_read_file = os.open(FIFO_FILE_PATH, os.O_RDONLY | os.O_NONBLOCK) + fifo_write_file = os.open(FIFO_FILE_PATH, os.O_WRONLY) + + Popen( + ["xsel", "-p"], + stdout=fifo_write_file, + ) + os.close(fifo_write_file) + + if not PID_FILE_PATH.exists(): + speak_ng_process = Popen( + [ + "speak-ng", + f"-s {words_per_minute}", + ], + stdin=fifo_read_file, + ) + os.close(fifo_read_file) + + with PID_FILE_PATH.open("w") as pid_file: + pid_file.write(str(speak_ng_process.pid)) + + try: + speak_ng_process.wait() + except KeyboardInterrupt as e: + os.remove(PID_FILE_PATH) + + os.remove(PID_FILE_PATH) diff --git a/clipboard-speaker-kill b/clipboard-speaker-kill @@ -1,8 +1,14 @@ -#!/bin/sh +#!/usr/bin/env python3 -clipboard_speaker_directory="$HOME/.clipboard-speaker/" -pid_file_path="$clipboard_speaker_directory/pid" +import os +import pathlib +import signal -[ -f "$pid_file_path" ] && kill "$(cat "$pid_file_path")" +CLIPBOARD_SPEAKER_PATH = pathlib.Path.home() / ".clipboard-speaker" +PID_FILE_PATH = CLIPBOARD_SPEAKER_PATH / "pid" -rm "$pid_file_path" +if __name__ == "__main__": + with PID_FILE_PATH.open("r") as pid_file: + pid = int(pid_file.read()) + os.remove(PID_FILE_PATH) + os.kill(pid, signal.SIGTERM) diff --git a/clipboard-speaker-kill.py b/clipboard-speaker-kill.py @@ -1,14 +0,0 @@ -#!/usr/bin/env python3 - -import os -import pathlib -import signal - -CLIPBOARD_SPEAKER_PATH = pathlib.Path.home() / ".clipboard-speaker" -PID_FILE_PATH = CLIPBOARD_SPEAKER_PATH / "pid" - -if __name__ == "__main__": - with PID_FILE_PATH.open("r") as pid_file: - pid = int(pid_file.read()) - os.remove(PID_FILE_PATH) - os.kill(pid, signal.SIGTERM) diff --git a/clipboard-speaker.py b/clipboard-speaker.py @@ -1,63 +0,0 @@ -#!/usr/bin/env python3 - -import os -from pathlib import Path -from subprocess import Popen, PIPE - -DEFAULT_WORDS_PER_MINUTE = "175" - -CLIPBOARD_SPEAKER_PATH = Path.home() / ".clipboard-speaker" -PID_FILE_PATH = CLIPBOARD_SPEAKER_PATH / "pid" -FIFO_FILE_PATH = CLIPBOARD_SPEAKER_PATH / "fifo" - -WORDS_PER_MINUTE_PATH = CLIPBOARD_SPEAKER_PATH / "words-per-minute" - - -def get_words_per_minute() -> str: - if not WORDS_PER_MINUTE_PATH.exists(): - with WORDS_PER_MINUTE_PATH.open("w") as words_per_minute_file: - words_per_minute_file.write(DEFAULT_WORDS_PER_MINUTE) - return DEFAULT_WORDS_PER_MINUTE - - with WORDS_PER_MINUTE_PATH.open("r") as words_per_minute_file: - words_per_minute = words_per_minute_file.read().strip() - - return words_per_minute - - -if __name__ == "__main__": - words_per_minute = get_words_per_minute() - try: - os.mkfifo(FIFO_FILE_PATH, mode=0o600) - except FileExistsError: - pass - - # https://stackoverflow.com/questions/63132778/how-to-use-fifo-named-pipe-as-stdin-in-popen-python - fifo_read_file = os.open(FIFO_FILE_PATH, os.O_RDONLY | os.O_NONBLOCK) - fifo_write_file = os.open(FIFO_FILE_PATH, os.O_WRONLY) - - Popen( - ["xsel", "-p"], - stdout=fifo_write_file, - ) - os.close(fifo_write_file) - - if not PID_FILE_PATH.exists(): - speak_ng_process = Popen( - [ - "speak-ng", - f"-s {words_per_minute}", - ], - stdin=fifo_read_file, - ) - os.close(fifo_read_file) - - with PID_FILE_PATH.open("w") as pid_file: - pid_file.write(str(speak_ng_process.pid)) - - try: - speak_ng_process.wait() - except KeyboardInterrupt as e: - os.remove(PID_FILE_PATH) - - os.remove(PID_FILE_PATH) diff --git a/clipboard-speaker b/old-shell-version/clipboard-speaker diff --git a/clipboard-speaker-kill b/old-shell-version/clipboard-speaker-kill