The template was expanding KEY_LEFTCTRL, KEY_RIGHTCTRL but only prepending ecodes. to the first one. Now all key codes include the ecodes. prefix in the case statement values. https://claude.ai/code/session_01XKYC1basxdwtHy71tky7xm
590 lines
19 KiB
Bash
Executable File
590 lines
19 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# setup-ptt.sh — One-shot setup for OpenWhispr Push-to-Talk
|
|
# https://github.com/outis1one/openwhispr-easy-setup
|
|
# License: MIT
|
|
|
|
main() {
|
|
|
|
SCRIPT_VERSION="1.0.0"
|
|
PTT_DIR="$HOME/.local/share/openwhispr-ptt"
|
|
PTT_SCRIPT="$PTT_DIR/openwhispr-ptt.py"
|
|
UNINSTALL_SCRIPT="$PTT_DIR/uninstall-ptt.sh"
|
|
SERVICE_NAME="openwhispr-ptt"
|
|
SERVICE_FILE="$HOME/.config/systemd/user/${SERVICE_NAME}.service"
|
|
|
|
# ── Colours ───────────────────────────────────────────────────────────────
|
|
|
|
if [[ -t 1 ]]; then
|
|
BOLD='\033[1m' GREEN='\033[0;32m' YELLOW='\033[0;33m'
|
|
RED='\033[0;31m' CYAN='\033[0;36m' DIM='\033[2m' RESET='\033[0m'
|
|
else
|
|
BOLD='' GREEN='' YELLOW='' RED='' CYAN='' DIM='' RESET=''
|
|
fi
|
|
|
|
# shellcheck disable=SC2059
|
|
info() { printf "${GREEN}[✓]${RESET} %s\n" "$*"; }
|
|
# shellcheck disable=SC2059
|
|
warn() { printf "${YELLOW}[!]${RESET} %s\n" "$*"; }
|
|
# shellcheck disable=SC2059
|
|
err() { printf "${RED}[✗]${RESET} %s\n" "$*" >&2; }
|
|
# shellcheck disable=SC2059
|
|
step() { printf "\n${BOLD}${CYAN}[%s]${RESET} ${BOLD}%s${RESET}\n" "$1" "$2"; }
|
|
# shellcheck disable=SC2059
|
|
divider() { printf "${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n"; }
|
|
|
|
ask() {
|
|
local prompt="$1" default="$2" varname="$3" reply
|
|
printf "%s [default: %s]: " "$prompt" "$default" > /dev/tty
|
|
read -r reply < /dev/tty
|
|
reply="${reply:-$default}"
|
|
printf -v "$varname" '%s' "$reply"
|
|
}
|
|
|
|
# ══════════════════════════════════════════════════════════════════════════
|
|
# [1/6] Intro
|
|
# ══════════════════════════════════════════════════════════════════════════
|
|
|
|
step "1/6" "OpenWhispr Push-to-Talk Setup v${SCRIPT_VERSION}"
|
|
divider
|
|
cat <<'INTRO'
|
|
This script sets up push-to-talk (hold-to-talk) for OpenWhispr.
|
|
|
|
Hold a key combo → OpenWhispr starts listening
|
|
Release → OpenWhispr stops and transcribes
|
|
|
|
What it will do:
|
|
1. Add your user to the 'input' group (no sudo needed for PTT)
|
|
2. Install Python dependencies (evdev)
|
|
3. Create the PTT script
|
|
4. Let you choose your PTT hotkey
|
|
5. Set up a systemd service (auto-start, auto-restart)
|
|
6. Create an uninstall script
|
|
INTRO
|
|
divider
|
|
printf "\nPress Enter to continue or Ctrl-C to cancel... " > /dev/tty
|
|
read -r < /dev/tty
|
|
|
|
# ══════════════════════════════════════════════════════════════════════════
|
|
# [2/6] Dependencies
|
|
# ══════════════════════════════════════════════════════════════════════════
|
|
|
|
step "2/6" "Dependencies"
|
|
|
|
# Check for OpenWhispr
|
|
OW_INSTALLED=false
|
|
if command -v open-whispr >/dev/null 2>&1 || \
|
|
command -v openwhispr >/dev/null 2>&1 || \
|
|
dpkg -l open-whispr 2>/dev/null | grep -q '^ii'; then
|
|
OW_INSTALLED=true
|
|
info "OpenWhispr is installed."
|
|
else
|
|
err "OpenWhispr does not appear to be installed."
|
|
err "Install it first: https://github.com/OpenWhispr/openwhispr/releases"
|
|
exit 1
|
|
fi
|
|
|
|
# Check for xdotool
|
|
if command -v xdotool >/dev/null 2>&1; then
|
|
info "xdotool is installed."
|
|
else
|
|
warn "xdotool is required. Installing..."
|
|
sudo apt install -y xdotool || {
|
|
err "Failed to install xdotool."
|
|
exit 1
|
|
}
|
|
info "xdotool installed."
|
|
fi
|
|
|
|
# Add user to input group
|
|
if groups "$USER" | grep -qw input; then
|
|
info "User '$USER' is already in the 'input' group."
|
|
else
|
|
warn "Adding '$USER' to the 'input' group (requires sudo)..."
|
|
sudo usermod -aG input "$USER" || {
|
|
err "Failed to add user to input group."
|
|
exit 1
|
|
}
|
|
info "Added '$USER' to 'input' group."
|
|
warn "You will need to log out and back in for this to take effect."
|
|
NEEDS_RELOGIN=true
|
|
fi
|
|
|
|
# Install evdev Python module
|
|
if python3 -c "import evdev" 2>/dev/null; then
|
|
info "Python evdev module is installed."
|
|
else
|
|
warn "Installing Python evdev module..."
|
|
pip3 install evdev --break-system-packages 2>/dev/null || \
|
|
sudo pip3 install evdev --break-system-packages 2>/dev/null || {
|
|
err "Failed to install evdev."
|
|
exit 1
|
|
}
|
|
info "evdev installed."
|
|
fi
|
|
|
|
# ══════════════════════════════════════════════════════════════════════════
|
|
# [3/6] Choose PTT hotkey
|
|
# ══════════════════════════════════════════════════════════════════════════
|
|
|
|
step "3/6" "Choose your Push-to-Talk hotkey"
|
|
|
|
cat <<'HOTKEY_MENU'
|
|
|
|
Which key combo do you want to HOLD for push-to-talk?
|
|
|
|
1) Ctrl + Alt (recommended — works on all desktops)
|
|
2) Ctrl + Shift
|
|
3) Alt + Shift
|
|
4) Right Ctrl alone (easy one-hand use)
|
|
5) Right Alt alone (easy one-hand use)
|
|
|
|
Note: Avoid Super/Windows key — most desktops intercept it.
|
|
The OpenWhispr toggle hotkey (Ctrl+`) must NOT conflict.
|
|
|
|
HOTKEY_MENU
|
|
|
|
ask "Enter 1-5" "1" HOTKEY_CHOICE
|
|
|
|
case "$HOTKEY_CHOICE" in
|
|
1)
|
|
PTT_LABEL="Ctrl + Alt"
|
|
PTT_KEY1_NAME="ctrl"
|
|
PTT_KEY2_NAME="alt"
|
|
PTT_KEY1_CODES="ecodes.KEY_LEFTCTRL, ecodes.KEY_RIGHTCTRL"
|
|
PTT_KEY2_CODES="ecodes.KEY_LEFTALT, ecodes.KEY_RIGHTALT"
|
|
;;
|
|
2)
|
|
PTT_LABEL="Ctrl + Shift"
|
|
PTT_KEY1_NAME="ctrl"
|
|
PTT_KEY2_NAME="shift"
|
|
PTT_KEY1_CODES="ecodes.KEY_LEFTCTRL, ecodes.KEY_RIGHTCTRL"
|
|
PTT_KEY2_CODES="ecodes.KEY_LEFTSHIFT, ecodes.KEY_RIGHTSHIFT"
|
|
;;
|
|
3)
|
|
PTT_LABEL="Alt + Shift"
|
|
PTT_KEY1_NAME="alt"
|
|
PTT_KEY2_NAME="shift"
|
|
PTT_KEY1_CODES="ecodes.KEY_LEFTALT, ecodes.KEY_RIGHTALT"
|
|
PTT_KEY2_CODES="ecodes.KEY_LEFTSHIFT, ecodes.KEY_RIGHTSHIFT"
|
|
;;
|
|
4)
|
|
PTT_LABEL="Right Ctrl (alone)"
|
|
PTT_KEY1_NAME="rctrl"
|
|
PTT_KEY2_NAME=""
|
|
PTT_KEY1_CODES="ecodes.KEY_RIGHTCTRL"
|
|
PTT_KEY2_CODES=""
|
|
;;
|
|
5)
|
|
PTT_LABEL="Right Alt (alone)"
|
|
PTT_KEY1_NAME="ralt"
|
|
PTT_KEY2_NAME=""
|
|
PTT_KEY1_CODES="ecodes.KEY_RIGHTALT"
|
|
PTT_KEY2_CODES=""
|
|
;;
|
|
*)
|
|
warn "Invalid choice — defaulting to Ctrl + Alt."
|
|
PTT_LABEL="Ctrl + Alt"
|
|
PTT_KEY1_NAME="ctrl"
|
|
PTT_KEY2_NAME="alt"
|
|
PTT_KEY1_CODES="ecodes.KEY_LEFTCTRL, ecodes.KEY_RIGHTCTRL"
|
|
PTT_KEY2_CODES="ecodes.KEY_LEFTALT, ecodes.KEY_RIGHTALT"
|
|
;;
|
|
esac
|
|
|
|
info "PTT hotkey: ${PTT_LABEL}"
|
|
|
|
# ══════════════════════════════════════════════════════════════════════════
|
|
# [4/6] Create PTT script
|
|
# ══════════════════════════════════════════════════════════════════════════
|
|
|
|
step "4/6" "Creating PTT script"
|
|
|
|
mkdir -p "$PTT_DIR"
|
|
|
|
# Generate the appropriate Python code based on single vs dual key
|
|
if [[ -z "$PTT_KEY2_NAME" ]]; then
|
|
# Single key mode
|
|
cat > "$PTT_SCRIPT" << PYEOF
|
|
#!/usr/bin/env python3
|
|
"""
|
|
openwhispr-ptt.py — Push-to-talk wrapper for OpenWhispr
|
|
PTT hotkey: ${PTT_LABEL}
|
|
Generated by setup-ptt.sh v${SCRIPT_VERSION}
|
|
"""
|
|
|
|
import subprocess
|
|
import signal
|
|
import sys
|
|
import time
|
|
|
|
try:
|
|
import evdev
|
|
from evdev import ecodes
|
|
except ImportError:
|
|
print("Error: evdev not installed.")
|
|
print("Install with: pip3 install evdev --break-system-packages")
|
|
sys.exit(1)
|
|
|
|
WHISPR_HOTKEY_UP = ["xdotool", "keyup", "ctrl", "alt", "super"]
|
|
WHISPR_HOTKEY_SEND = ["xdotool", "keydown", "ctrl", "key", "grave", "keyup", "ctrl"]
|
|
PTT_CODES = (${PTT_KEY1_CODES},)
|
|
|
|
is_recording = False
|
|
|
|
|
|
def send_whispr_toggle():
|
|
try:
|
|
subprocess.run(WHISPR_HOTKEY_UP, timeout=2, capture_output=True)
|
|
subprocess.run(WHISPR_HOTKEY_SEND, timeout=2, capture_output=True)
|
|
except FileNotFoundError:
|
|
print("Error: xdotool not installed.")
|
|
sys.exit(1)
|
|
except subprocess.TimeoutExpired:
|
|
pass
|
|
|
|
|
|
def find_keyboard():
|
|
devices = [evdev.InputDevice(path) for path in evdev.list_devices()]
|
|
for dev in devices:
|
|
name_lower = dev.name.lower()
|
|
if "virtual" in name_lower or "ydotool" in name_lower:
|
|
continue
|
|
caps = dev.capabilities(verbose=False)
|
|
if ecodes.EV_KEY in caps:
|
|
keys = caps[ecodes.EV_KEY]
|
|
if ecodes.KEY_A in keys and ecodes.KEY_LEFTCTRL in keys:
|
|
return dev
|
|
return None
|
|
|
|
|
|
def main():
|
|
global is_recording
|
|
|
|
print("=" * 47)
|
|
print(" OpenWhispr Push-to-Talk")
|
|
print("=" * 47)
|
|
print(" Hold: ${PTT_LABEL} -> start dictation")
|
|
print(" Release: ${PTT_LABEL} -> stop dictation")
|
|
print(" Quit: Ctrl + C")
|
|
print("=" * 47)
|
|
|
|
kb = find_keyboard()
|
|
if kb is None:
|
|
print("\\nError: No keyboard found.")
|
|
print("Check: groups | grep input")
|
|
print("Fix: sudo usermod -aG input \$USER (then log out/in)")
|
|
sys.exit(1)
|
|
|
|
print(f" Keyboard: {kb.name}")
|
|
print("=" * 47)
|
|
print("Listening...\\n")
|
|
|
|
signal.signal(signal.SIGINT, lambda *_: sys.exit(0))
|
|
|
|
for event in kb.read_loop():
|
|
if event.type != ecodes.EV_KEY or event.value == 2:
|
|
continue
|
|
|
|
if event.code in PTT_CODES:
|
|
if event.value == 1 and not is_recording:
|
|
is_recording = True
|
|
send_whispr_toggle()
|
|
print("\\033[32m● Recording...\\033[0m", flush=True)
|
|
elif event.value == 0 and is_recording:
|
|
time.sleep(0.05)
|
|
send_whispr_toggle()
|
|
is_recording = False
|
|
print("\\033[0m○ Stopped", flush=True)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
PYEOF
|
|
|
|
else
|
|
# Dual key mode
|
|
cat > "$PTT_SCRIPT" << PYEOF
|
|
#!/usr/bin/env python3
|
|
"""
|
|
openwhispr-ptt.py — Push-to-talk wrapper for OpenWhispr
|
|
PTT hotkey: ${PTT_LABEL}
|
|
Generated by setup-ptt.sh v${SCRIPT_VERSION}
|
|
"""
|
|
|
|
import subprocess
|
|
import signal
|
|
import sys
|
|
import time
|
|
|
|
try:
|
|
import evdev
|
|
from evdev import ecodes
|
|
except ImportError:
|
|
print("Error: evdev not installed.")
|
|
print("Install with: pip3 install evdev --break-system-packages")
|
|
sys.exit(1)
|
|
|
|
WHISPR_HOTKEY_UP = ["xdotool", "keyup", "ctrl", "alt", "super"]
|
|
WHISPR_HOTKEY_SEND = ["xdotool", "keydown", "ctrl", "key", "grave", "keyup", "ctrl"]
|
|
KEY1_CODES = (${PTT_KEY1_CODES},)
|
|
KEY2_CODES = (${PTT_KEY2_CODES},)
|
|
|
|
key1_held = False
|
|
key2_held = False
|
|
is_recording = False
|
|
|
|
|
|
def send_whispr_toggle():
|
|
try:
|
|
subprocess.run(WHISPR_HOTKEY_UP, timeout=2, capture_output=True)
|
|
subprocess.run(WHISPR_HOTKEY_SEND, timeout=2, capture_output=True)
|
|
except FileNotFoundError:
|
|
print("Error: xdotool not installed.")
|
|
sys.exit(1)
|
|
except subprocess.TimeoutExpired:
|
|
pass
|
|
|
|
|
|
def find_keyboard():
|
|
devices = [evdev.InputDevice(path) for path in evdev.list_devices()]
|
|
for dev in devices:
|
|
name_lower = dev.name.lower()
|
|
if "virtual" in name_lower or "ydotool" in name_lower:
|
|
continue
|
|
caps = dev.capabilities(verbose=False)
|
|
if ecodes.EV_KEY in caps:
|
|
keys = caps[ecodes.EV_KEY]
|
|
if ecodes.KEY_A in keys and ecodes.KEY_LEFTCTRL in keys:
|
|
return dev
|
|
return None
|
|
|
|
|
|
def main():
|
|
global key1_held, key2_held, is_recording
|
|
|
|
print("=" * 47)
|
|
print(" OpenWhispr Push-to-Talk")
|
|
print("=" * 47)
|
|
print(" Hold: ${PTT_LABEL} -> start dictation")
|
|
print(" Release: ${PTT_LABEL} -> stop dictation")
|
|
print(" Quit: Ctrl + C")
|
|
print("=" * 47)
|
|
|
|
kb = find_keyboard()
|
|
if kb is None:
|
|
print("\\nError: No keyboard found.")
|
|
print("Check: groups | grep input")
|
|
print("Fix: sudo usermod -aG input \$USER (then log out/in)")
|
|
sys.exit(1)
|
|
|
|
print(f" Keyboard: {kb.name}")
|
|
print("=" * 47)
|
|
print("Listening...\\n")
|
|
|
|
signal.signal(signal.SIGINT, lambda *_: sys.exit(0))
|
|
|
|
for event in kb.read_loop():
|
|
if event.type != ecodes.EV_KEY or event.value == 2:
|
|
continue
|
|
|
|
pressed = (event.value == 1)
|
|
|
|
if event.code in KEY1_CODES:
|
|
key1_held = pressed
|
|
elif event.code in KEY2_CODES:
|
|
key2_held = pressed
|
|
|
|
if key1_held and key2_held and not is_recording:
|
|
is_recording = True
|
|
send_whispr_toggle()
|
|
print("\\033[32m● Recording...\\033[0m", flush=True)
|
|
|
|
if is_recording and not (key1_held and key2_held):
|
|
time.sleep(0.05)
|
|
send_whispr_toggle()
|
|
is_recording = False
|
|
print("\\033[0m○ Stopped", flush=True)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
PYEOF
|
|
|
|
fi
|
|
|
|
chmod +x "$PTT_SCRIPT"
|
|
info "PTT script created: $PTT_SCRIPT"
|
|
|
|
# ══════════════════════════════════════════════════════════════════════════
|
|
# [5/6] Create systemd service
|
|
# ══════════════════════════════════════════════════════════════════════════
|
|
|
|
step "5/6" "Setting up systemd service"
|
|
|
|
mkdir -p "$HOME/.config/systemd/user"
|
|
|
|
cat > "$SERVICE_FILE" << SVCEOF
|
|
[Unit]
|
|
Description=OpenWhispr Push-to-Talk (${PTT_LABEL})
|
|
Documentation=https://github.com/outis1one/openwhispr-easy-setup
|
|
After=graphical-session.target
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=5
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStart=/usr/bin/python3 ${PTT_SCRIPT}
|
|
Restart=on-failure
|
|
RestartSec=3
|
|
Environment=DISPLAY=:0
|
|
Environment=XAUTHORITY=%h/.Xauthority
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
SVCEOF
|
|
|
|
systemctl --user daemon-reload
|
|
info "Systemd service created: $SERVICE_FILE"
|
|
|
|
# Enable but don't start yet if relogin needed
|
|
systemctl --user enable "$SERVICE_NAME" 2>/dev/null
|
|
info "Service enabled (will start on login)."
|
|
|
|
# Try to start now if input group is already active
|
|
if groups "$USER" | grep -qw input && [[ -z "${NEEDS_RELOGIN:-}" ]]; then
|
|
systemctl --user start "$SERVICE_NAME" 2>/dev/null
|
|
if systemctl --user is-active "$SERVICE_NAME" >/dev/null 2>&1; then
|
|
info "Service started successfully."
|
|
else
|
|
warn "Service failed to start. Check: journalctl --user -u $SERVICE_NAME"
|
|
fi
|
|
else
|
|
warn "Service will start after you log out and back in."
|
|
fi
|
|
|
|
# ══════════════════════════════════════════════════════════════════════════
|
|
# [6/6] Create uninstall script & check OpenWhispr
|
|
# ══════════════════════════════════════════════════════════════════════════
|
|
|
|
step "6/6" "Finishing up"
|
|
|
|
# Create uninstall script
|
|
cat > "$UNINSTALL_SCRIPT" << 'UNINSTEOF'
|
|
#!/usr/bin/env bash
|
|
echo "Uninstalling OpenWhispr PTT..."
|
|
|
|
# Stop and disable service
|
|
systemctl --user stop openwhispr-ptt 2>/dev/null
|
|
systemctl --user disable openwhispr-ptt 2>/dev/null
|
|
rm -f "$HOME/.config/systemd/user/openwhispr-ptt.service"
|
|
systemctl --user daemon-reload
|
|
|
|
# Remove PTT files
|
|
rm -rf "$HOME/.local/share/openwhispr-ptt"
|
|
|
|
echo ""
|
|
echo "OpenWhispr PTT has been uninstalled."
|
|
echo "Note: OpenWhispr itself was NOT removed."
|
|
echo "Note: User was NOT removed from 'input' group."
|
|
echo " To remove: sudo gpasswd -d $USER input"
|
|
UNINSTEOF
|
|
chmod +x "$UNINSTALL_SCRIPT"
|
|
info "Uninstall script created: $UNINSTALL_SCRIPT"
|
|
|
|
# Check if OpenWhispr is running
|
|
OW_RUNNING=false
|
|
if pgrep -f "open-whispr" >/dev/null 2>&1; then
|
|
OW_RUNNING=true
|
|
info "OpenWhispr is running."
|
|
else
|
|
warn "OpenWhispr is not running."
|
|
printf "Start OpenWhispr now? [Y/n]: " > /dev/tty
|
|
read -r ow_reply < /dev/tty
|
|
ow_reply="${ow_reply:-Y}"
|
|
if [[ "${ow_reply,,}" == "y" ]]; then
|
|
# Find and launch
|
|
for cmd in open-whispr openwhispr; do
|
|
if command -v "$cmd" >/dev/null 2>&1; then
|
|
"$cmd" &>/dev/null &
|
|
info "OpenWhispr launched."
|
|
OW_RUNNING=true
|
|
break
|
|
fi
|
|
done
|
|
if [[ "$OW_RUNNING" != true ]]; then
|
|
# Try common paths
|
|
for path in /opt/OpenWhispr/open-whispr /usr/lib/open-whispr/open-whispr; do
|
|
if [[ -x "$path" ]]; then
|
|
"$path" &>/dev/null &
|
|
info "OpenWhispr launched."
|
|
OW_RUNNING=true
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
if [[ "$OW_RUNNING" != true ]]; then
|
|
# Try dpkg
|
|
local_bin="$(dpkg -L open-whispr 2>/dev/null | grep -E '/bin/|/opt/' | head -1)"
|
|
if [[ -n "$local_bin" && -x "$local_bin" ]]; then
|
|
"$local_bin" &>/dev/null &
|
|
info "OpenWhispr launched."
|
|
OW_RUNNING=true
|
|
else
|
|
warn "Could not find OpenWhispr binary. Launch it manually."
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# ── Summary ───────────────────────────────────────────────────────────────
|
|
|
|
printf "\n"
|
|
divider
|
|
# shellcheck disable=SC2059
|
|
printf "${BOLD} OpenWhispr PTT is ready${RESET}\n"
|
|
divider
|
|
cat << EOF
|
|
|
|
PTT hotkey: ${PTT_LABEL} (hold to talk, release to stop)
|
|
OW hotkey: Ctrl + \` (used internally — don't change in OW)
|
|
|
|
Files:
|
|
PTT script: ${PTT_SCRIPT}
|
|
Service: ${SERVICE_FILE}
|
|
Uninstall: ${UNINSTALL_SCRIPT}
|
|
|
|
EOF
|
|
|
|
if [[ -n "${NEEDS_RELOGIN:-}" ]]; then
|
|
cat << 'EOF'
|
|
⚠ LOG OUT AND BACK IN for input group to take effect.
|
|
After re-login the PTT service will start automatically.
|
|
|
|
EOF
|
|
fi
|
|
|
|
cat << 'EOF'
|
|
Useful commands:
|
|
systemctl --user status openwhispr-ptt check PTT status
|
|
systemctl --user restart openwhispr-ptt restart PTT
|
|
systemctl --user stop openwhispr-ptt stop PTT
|
|
journalctl --user -u openwhispr-ptt -f view PTT logs
|
|
|
|
systemctl --user start openwhispr-ptt manual start
|
|
systemctl --user disable openwhispr-ptt disable auto-start
|
|
systemctl --user enable openwhispr-ptt re-enable auto-start
|
|
|
|
Test PTT manually:
|
|
python3 ~/.local/share/openwhispr-ptt/openwhispr-ptt.py
|
|
|
|
Uninstall:
|
|
bash ~/.local/share/openwhispr-ptt/uninstall-ptt.sh
|
|
|
|
EOF
|
|
divider
|
|
printf "\n"
|
|
|
|
} # end main()
|
|
|
|
main "$@"
|