Files
Arch-R/scripts/opt-system/menu-lib.sh
Douglas Teles c8e7fe99e9 Add ES Tools menu scripts and gptokeyb configs (WIP)
Interactive tool scripts for EmulationStation's OPTIONS menu at /opt/system/:
system-info, wifi-setup, bluetooth-setup, performance-mode, suspend-mode,
usb-mode, factory-reset. Uses shared menu-lib.sh with fbcon rendering.

Gamepad configs: default.gptk (RetroArch), tools.gptk (menu navigation
with D-pad arrows, A=enter, B=escape).

Note: scripts need further testing on hardware — left disabled for now.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:22:49 -03:00

124 lines
3.3 KiB
Bash

#!/bin/bash
# Arch R — Shared menu library for system tools
# Source this at the top of each tool script:
# . /usr/lib/archr/menu-lib.sh
#
# Provides:
# tool_init — start gptokeyb, set up console
# tool_cleanup — kill gptokeyb (called automatically on exit)
# menu_select TITLE ITEM1 ITEM2 ... — interactive menu, sets MENU_RESULT
# msg_show TITLE TEXT — display text, wait for A/B to return
#
# gptokeyb maps: D-pad=arrows, A/Start=Enter, B/Back=Escape
export TERM=linux
GPTK_PID=""
tool_init() {
# Redirect stdin from tty1 (ES may have it as /dev/null)
exec < /dev/tty1
# Force fbcon redraw by clearing the console
clear
# Start gptokeyb for gamepad → keyboard mapping
if [ -x /usr/local/bin/archr-gptokeyb ]; then
/usr/local/bin/archr-gptokeyb "tool-menu" \
-c /etc/archr/gptokeyb/tools.gptk &>/dev/null &
GPTK_PID=$!
# Wait for uinput device to register
sleep 0.2
fi
}
tool_cleanup() {
# Kill gptokeyb if we started it
if [ -n "$GPTK_PID" ]; then
kill "$GPTK_PID" 2>/dev/null
wait "$GPTK_PID" 2>/dev/null
GPTK_PID=""
fi
# Show cursor
tput cnorm 2>/dev/null
}
# Ensure cleanup runs on exit
trap tool_cleanup EXIT
# menu_select TITLE ITEM1 ITEM2 ...
# Sets MENU_RESULT to selected index (0-based)
# Returns 0 on select (A/Enter), 1 on cancel (B/Escape)
menu_select() {
local title="$1"; shift
local options=("$@")
local selected=0
local count=${#options[@]}
tput civis 2>/dev/null # hide cursor
while true; do
clear
echo "==============================="
echo " $title"
echo "==============================="
echo ""
for i in "${!options[@]}"; do
if [ "$i" -eq "$selected" ]; then
# Highlighted: inverse video
echo -e " \e[7m> ${options[$i]}\e[0m"
else
echo " ${options[$i]}"
fi
done
echo ""
echo " [D-pad] Navigate [A] Select [B] Back"
# Read one character
IFS= read -rsn1 key
case "$key" in
$'\x1b')
# Escape sequence: read the rest (e.g. [A for up arrow)
IFS= read -rsn2 -t 0.2 seq
case "$seq" in
"[A") [ "$selected" -gt 0 ] && selected=$((selected - 1)) ;;
"[B") [ "$selected" -lt $((count - 1)) ] && selected=$((selected + 1)) ;;
esac
# Bare Escape (no seq) = cancel
[ -z "$seq" ] && { tput cnorm 2>/dev/null; return 1; }
;;
"")
# Enter key = select
tput cnorm 2>/dev/null
MENU_RESULT=$selected
return 0
;;
esac
done
}
# msg_show TITLE TEXT
# Displays text and waits for any key (A/B/Enter/Escape)
msg_show() {
local title="$1"; shift
local text="$*"
tput civis 2>/dev/null
clear
echo "==============================="
echo " $title"
echo "==============================="
echo ""
echo -e "$text"
echo ""
echo " [A/B] Back"
# Wait for any key
IFS= read -rsn1 _
# Consume escape sequence if arrow key was pressed
IFS= read -rsn2 -t 0.1 _ 2>/dev/null
tput cnorm 2>/dev/null
}