#!/bin/sh set -eu SESSION="pi-voice" APP_ID="pi-voice" TITLE="Pi Voice" OUT="${XDG_RUNTIME_DIR:-/tmp}/pi-voice-query.txt" STATUS_SCRIPT="$HOME/.config/sway/status.sh" refresh_bar() { pkill -USR1 -f "$STATUS_SCRIPT" 2>/dev/null || true } position_pi_window() { # Size scratchpad window to 60% of the focused output using absolute pixels. # Doing this here is more reliable than a for_window percentage resize. set -- $(swaymsg -t get_outputs 2>/dev/null | python3 -c ' import json, sys outs = json.load(sys.stdin) out = next((o for o in outs if o.get("focused")), None) or next((o for o in outs if o.get("active")), None) rect = (out or {}).get("rect", {}) w = int(rect.get("width", 1200) * 0.6) h = int(rect.get("height", 800) * 0.6) print(w, h) ') w=${1:-1200} h=${2:-800} swaymsg '[app_id="'"$APP_ID"'"] border pixel 2, resize set width '"$w"' px height '"$h"' px, move position center' >/dev/null 2>&1 || true } ensure_pi_terminal() { if ! tmux has-session -t "$SESSION" 2>/dev/null; then tmux new-session -d -s "$SESSION" 'pi' fi if command -v swaymsg >/dev/null 2>&1; then if ! swaymsg -t get_tree 2>/dev/null | grep -q '"app_id": "'"$APP_ID"'"'; then foot --app-id="$APP_ID" --title="$TITLE" \ --override=main.resize-by-cells=no \ --override=colors.alpha=1.0 \ --override=main.pad=0x0 \ tmux attach-session -t "$SESSION" >/dev/null 2>&1 & # Give the window a moment to appear before trying to show/focus it. sleep 0.5 fi swaymsg '[app_id="'"$APP_ID"'"] scratchpad show, focus' >/dev/null 2>&1 || true position_pi_window fi } send_to_pi() { text=$1 [ -n "$text" ] || exit 0 ensure_pi_terminal # Paste literally, then press Enter to submit to pi. printf '%s' "$text" | tmux load-buffer - tmux paste-buffer -t "$SESSION" tmux send-keys -t "$SESSION" Enter } case "${1:-}" in start) ensure_pi_terminal : > "$OUT" voxtype record start --file="$OUT" refresh_bar ;; stop) voxtype record stop refresh_bar # Wait for transcription to land in OUT. Stop early once voxtype is idle # and the file has text, otherwise allow slower large-model runs. i=0 while [ "$i" -lt 180 ]; do if [ -s "$OUT" ]; then break fi state=$(voxtype status 2>/dev/null || true) [ "$state" = idle ] && [ "$i" -gt 2 ] && break sleep 0.5 i=$((i + 1)) done refresh_bar text=$(cat "$OUT" 2>/dev/null || true) send_to_pi "$text" ;; *) echo "usage: $0 start|stop" >&2 exit 2 ;; esac