419 lines
12 KiB
Bash
419 lines
12 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# Dialog interface wrapper for audiogame-manager
|
|
# Automatically switches between dialog (console) and yad (GUI) based on DISPLAY environment
|
|
# This provides better accessibility for GUI environments while maintaining console functionality
|
|
|
|
# Note: dialogType is now detected in the main script before DISPLAY is modified
|
|
# This ensures console detection works correctly when AGM sets DISPLAY=":0"
|
|
# If dialogType is not set (e.g., when called from standalone scripts), detect it
|
|
if [[ -z "$dialogType" ]]; then
|
|
if [[ -z "$DISPLAY" ]]; then
|
|
dialogType="dialog"
|
|
else
|
|
dialogType="yad"
|
|
fi
|
|
fi
|
|
|
|
# Wrapper function for menu selection
|
|
# Usage: agm_menu "title" "backtitle" "text" option1 "description1" option2 "description2" ...
|
|
agm_menu() {
|
|
local title="$1"
|
|
local backTitle="$2"
|
|
local text="$3"
|
|
shift 3
|
|
|
|
if [[ "$dialogType" == "yad" ]]; then
|
|
# Build yad list format: Display only, then map back to value
|
|
local yadList=""
|
|
declare -A valueMap
|
|
while [[ $# -gt 0 ]]; do
|
|
local option="$1"
|
|
local description="$2"
|
|
valueMap["$description"]="$option"
|
|
if [[ -n "$yadList" ]]; then
|
|
yadList="$yadList\n"
|
|
fi
|
|
yadList="${yadList}${description}"
|
|
shift 2
|
|
done
|
|
|
|
local selectedDescription
|
|
selectedDescription=$(echo -e "$yadList" | yad --list \
|
|
--title="$title" \
|
|
--text="$text" \
|
|
--column="Option" \
|
|
--no-headers \
|
|
--selectable-labels \
|
|
--search-column=1 \
|
|
--height=400 \
|
|
--width=600)
|
|
|
|
# Strip trailing pipes and return the mapped value
|
|
if [[ -n "$selectedDescription" ]]; then
|
|
selectedDescription="${selectedDescription%|}"
|
|
echo "${valueMap["$selectedDescription"]}"
|
|
fi
|
|
else
|
|
# Build dialog menu format with mapping (same approach as yad)
|
|
local dialogArgs=()
|
|
declare -A valueMap
|
|
while [[ $# -gt 0 ]]; do
|
|
local option="$1"
|
|
local description="$2"
|
|
valueMap["$description"]="$option"
|
|
dialogArgs+=("$description" "$description")
|
|
shift 2
|
|
done
|
|
|
|
local selectedDescription
|
|
selectedDescription=$(dialog --backtitle "$backTitle" \
|
|
--title "$title" \
|
|
--no-tags \
|
|
--menu "$text" 0 0 0 \
|
|
"${dialogArgs[@]}" \
|
|
--stdout)
|
|
|
|
# Return the mapped value
|
|
if [[ -n "$selectedDescription" ]]; then
|
|
echo "${valueMap["$selectedDescription"]}"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Wrapper function for checklist selection
|
|
# Usage: agm_checklist "title" "backtitle" "text" option1 "description1" "status1" option2 "description2" "status2" ...
|
|
agm_checklist() {
|
|
local title="$1"
|
|
local backTitle="$2"
|
|
local text="$3"
|
|
shift 3
|
|
|
|
if [[ "$dialogType" == "yad" ]]; then
|
|
local yadList=""
|
|
while [[ $# -gt 0 ]]; do
|
|
local option="$1"
|
|
local description="$2"
|
|
local status="$3"
|
|
local checked="FALSE"
|
|
[[ "$status" == "on" ]] && checked="TRUE"
|
|
|
|
if [[ -n "$yadList" ]]; then
|
|
yadList="$yadList\n"
|
|
fi
|
|
yadList="${yadList}${checked}|${description}|${option}"
|
|
shift 3
|
|
done
|
|
|
|
echo -e "$yadList" | yad --list \
|
|
--title="$title" \
|
|
--text="$text" \
|
|
--checklist \
|
|
--column="Select:CHK" \
|
|
--column="Option" \
|
|
--column="Value:HD" \
|
|
--hide-column=3 \
|
|
--print-column=3 \
|
|
--no-headers \
|
|
--selectable-labels \
|
|
--height=400 \
|
|
--width=600 \
|
|
--separator=" "
|
|
else
|
|
local dialogArgs=()
|
|
while [[ $# -gt 0 ]]; do
|
|
dialogArgs+=("$1" "$2" "$3")
|
|
shift 3
|
|
done
|
|
|
|
dialog --backtitle "$backTitle" \
|
|
--title "$title" \
|
|
--checklist "$text" 0 0 0 \
|
|
"${dialogArgs[@]}" \
|
|
--stdout
|
|
fi
|
|
}
|
|
|
|
# Wrapper function for input dialog
|
|
# Usage: agm_inputbox "title" "backtitle" "text" "default_value"
|
|
agm_inputbox() {
|
|
local title="$1"
|
|
local backTitle="$2"
|
|
local text="$3"
|
|
local defaultValue="$4"
|
|
|
|
if [[ "$dialogType" == "yad" ]]; then
|
|
yad --entry \
|
|
--title="$title" \
|
|
--text="$text" \
|
|
--entry-text="$defaultValue" \
|
|
--selectable-labels \
|
|
--width=400
|
|
else
|
|
dialog --backtitle "$backTitle" \
|
|
--title "$title" \
|
|
--inputbox "$text" 0 0 "$defaultValue" \
|
|
--stdout
|
|
fi
|
|
}
|
|
|
|
# Wrapper function for message box
|
|
# Usage: agm_msgbox "title" "backtitle" "text"
|
|
agm_msgbox() {
|
|
local title="$1"
|
|
local backTitle="$2"
|
|
local text="$3"
|
|
|
|
if [[ "$dialogType" == "yad" ]]; then
|
|
yad --form \
|
|
--title="$title" \
|
|
--field="$text:LBL" \
|
|
--selectable-labels \
|
|
--button="OK:0" \
|
|
--width=400
|
|
else
|
|
dialog --backtitle "$backTitle" \
|
|
--title "$title" \
|
|
--msgbox "$text" 0 0
|
|
fi
|
|
}
|
|
|
|
# Wrapper function for yes/no dialog
|
|
# Usage: agm_yesno "title" "backtitle" "text"
|
|
agm_yesno() {
|
|
local title="$1"
|
|
local backTitle="$2"
|
|
local text="$3"
|
|
|
|
if [[ "$dialogType" == "yad" ]]; then
|
|
yad --form \
|
|
--title="$title" \
|
|
--field="$text:LBL" \
|
|
--selectable-labels \
|
|
--button="Yes:0" \
|
|
--button="No:1" \
|
|
--width=400
|
|
else
|
|
dialog --backtitle "$backTitle" \
|
|
--title "$title" \
|
|
--yesno "$text" 0 0
|
|
fi
|
|
}
|
|
|
|
# Wrapper function for info box (non-blocking message)
|
|
# Usage: agm_infobox "title" "backtitle" "text"
|
|
agm_infobox() {
|
|
local title="$1"
|
|
local backTitle="$2"
|
|
local text="$3"
|
|
|
|
if [[ "$dialogType" == "yad" ]]; then
|
|
# For yad, we'll use a notification since infobox is non-blocking
|
|
yad --notification \
|
|
--text="$text" \
|
|
--timeout=3
|
|
else
|
|
dialog --backtitle "$backTitle" \
|
|
--title "$title" \
|
|
--infobox "$text" 0 0
|
|
fi
|
|
}
|
|
|
|
# Wrapper function for progress box
|
|
# Usage: command | agm_progressbox "title" "text"
|
|
agm_progressbox() {
|
|
local title="$1"
|
|
local text="$2"
|
|
|
|
if [[ "$dialogType" == "yad" ]]; then
|
|
# Start audio feedback for accessibility
|
|
local beepPid
|
|
local yadPid
|
|
|
|
# Cleanup function for traps
|
|
cleanup_progress() {
|
|
[[ -n "$beepPid" ]] && kill "$beepPid" 2>/dev/null
|
|
[[ -n "$yadPid" ]] && kill "$yadPid" 2>/dev/null
|
|
}
|
|
|
|
# Set trap to ensure cleanup on interruption
|
|
trap cleanup_progress EXIT INT TERM
|
|
|
|
if command -v sox >/dev/null 2>&1; then
|
|
{
|
|
while true; do
|
|
# Generate a short, pleasant progress beep (440Hz for 0.1s)
|
|
sox -q -n -d synth 0.1 sine 440 vol 0.3 2>/dev/null
|
|
sleep 2 # Beep every 2 seconds
|
|
done
|
|
} &
|
|
beepPid=$!
|
|
fi
|
|
|
|
# Start visual progress dialog with auto-close
|
|
yad --progress \
|
|
--title="$title" \
|
|
--text="$text" \
|
|
--auto-close \
|
|
--pulsate \
|
|
--width=400 \
|
|
--height=100 &
|
|
yadPid=$!
|
|
|
|
# Process command output
|
|
local lineCount=0
|
|
local lastLine="Starting..."
|
|
while IFS= read -r line; do
|
|
((lineCount++))
|
|
lastLine="$line"
|
|
done < <(stdbuf -oL cat)
|
|
|
|
# Clean up background processes
|
|
cleanup_progress
|
|
trap - EXIT INT TERM # Remove traps
|
|
else
|
|
dialog --title "$title" \
|
|
--progressbox "$text" 20 70
|
|
fi
|
|
}
|
|
|
|
# Simple progress box that just shows the operation is running (no command output)
|
|
# Usage: command | agm_simple_progressbox "title" "text"
|
|
agm_simple_progressbox() {
|
|
local title="$1"
|
|
local text="$2"
|
|
|
|
if [[ "$dialogType" == "yad" ]]; then
|
|
# Start audio feedback for accessibility
|
|
local beepPid
|
|
local yadPid
|
|
|
|
# Cleanup function for traps
|
|
cleanup_simple_progress() {
|
|
[[ -n "$beepPid" ]] && kill "$beepPid" 2>/dev/null
|
|
[[ -n "$yadPid" ]] && kill "$yadPid" 2>/dev/null
|
|
}
|
|
|
|
# Set trap to ensure cleanup on interruption
|
|
trap cleanup_simple_progress EXIT INT TERM
|
|
|
|
if command -v sox >/dev/null 2>&1; then
|
|
{
|
|
while true; do
|
|
# Generate a short, pleasant progress beep (440Hz for 0.1s)
|
|
sox -q -n -d synth 0.1 sine 440 vol 0.3 2>/dev/null
|
|
sleep 2 # Beep every 2 seconds
|
|
done
|
|
} &
|
|
beepPid=$!
|
|
fi
|
|
|
|
# Show progress dialog with pulsating
|
|
yad --progress \
|
|
--title="$title" \
|
|
--text="$text" \
|
|
--auto-close \
|
|
--pulsate \
|
|
--width=400 \
|
|
--height=100 &
|
|
yadPid=$!
|
|
|
|
# Read from stdin and discard, but keep dialogs open until command finishes
|
|
cat > /dev/null
|
|
|
|
# Clean up background processes
|
|
cleanup_simple_progress
|
|
trap - EXIT INT TERM # Remove traps
|
|
else
|
|
dialog --title "$title" \
|
|
--progressbox "$text" 20 70
|
|
fi
|
|
}
|
|
|
|
# Alternative status box for simple operations without meaningful progress
|
|
# Usage: agm_statusbox "title" "text" & statusPid=$!; command; kill $statusPid 2>/dev/null
|
|
agm_statusbox() {
|
|
local title="$1"
|
|
local text="$2"
|
|
|
|
if [[ "$dialogType" == "yad" ]]; then
|
|
# Show a simple status message that screen readers can access
|
|
yad --form \
|
|
--title="$title" \
|
|
--field="$text:LBL" \
|
|
--selectable-labels \
|
|
--no-buttons \
|
|
--timeout=0 \
|
|
--width=400 \
|
|
--height=100
|
|
else
|
|
# Use infobox for console
|
|
dialog --title "$title" \
|
|
--infobox "$text" 5 50
|
|
fi
|
|
}
|
|
|
|
# Real progress bar with percentage updates (for operations that can report progress)
|
|
# Usage: agm_progress_with_percent "title" "text"
|
|
# Then send "percentage" or "#status text" to the returned file descriptor
|
|
agm_progress_with_percent() {
|
|
local title="$1"
|
|
local text="$2"
|
|
|
|
if [[ "$dialogType" == "yad" ]]; then
|
|
# Create a true progress dialog that accepts percentage updates
|
|
yad --progress \
|
|
--title="$title" \
|
|
--text="$text" \
|
|
--auto-close \
|
|
--width=400 \
|
|
--height=150
|
|
else
|
|
# For dialog, we'll simulate with a gauge
|
|
dialog --title "$title" \
|
|
--gauge "$text" 6 50 0
|
|
fi
|
|
}
|
|
|
|
# Wrapper function for file selection
|
|
# Usage: agm_fselect "title" "backtitle" "default_path"
|
|
agm_fselect() {
|
|
local title="$1"
|
|
local backTitle="$2"
|
|
local defaultPath="$3"
|
|
|
|
if [[ "$dialogType" == "yad" ]]; then
|
|
yad --file \
|
|
--title="$title" \
|
|
--filename="$defaultPath" \
|
|
--width=600 \
|
|
--height=400
|
|
else
|
|
dialog --backtitle "$backTitle" \
|
|
--title "$title" \
|
|
--fselect "$defaultPath" 0 0 \
|
|
--stdout
|
|
fi
|
|
}
|
|
|
|
# Wrapper function for directory selection
|
|
# Usage: agm_dselect "title" "backtitle" "default_path"
|
|
agm_dselect() {
|
|
local title="$1"
|
|
local backTitle="$2"
|
|
local defaultPath="$3"
|
|
|
|
if [[ "$dialogType" == "yad" ]]; then
|
|
yad --file \
|
|
--directory \
|
|
--title="$title" \
|
|
--filename="$defaultPath" \
|
|
--width=600 \
|
|
--height=400
|
|
else
|
|
dialog --backtitle "$backTitle" \
|
|
--title "$title" \
|
|
--dselect "$defaultPath" 0 0 \
|
|
--stdout
|
|
fi
|
|
} |