Added support for cthulhu's window reader plugin.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
# Get script directory for relative paths
|
||||
scriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
@@ -11,6 +12,136 @@ export DIALOGOPTS='--no-lines --visit-items'
|
||||
# Wine32 version for SAPI compatibility
|
||||
wineThirtyTwoVersion="9.0"
|
||||
|
||||
# Track nvda2speechd lifecycle for this launcher run.
|
||||
nvda2speechdPid=""
|
||||
nvda2speechdStarted="false"
|
||||
customLaunchHandled="false"
|
||||
cthulhuTitleReaderEnabled="false"
|
||||
cthulhuTitleReaderTried="false"
|
||||
|
||||
log_msg() {
|
||||
local logFile="${scriptDir}/game.log"
|
||||
local timestamp=""
|
||||
timestamp="$(date)"
|
||||
echo "${1} [${timestamp}]" >> "$logFile"
|
||||
}
|
||||
|
||||
start_nvda2speechd() {
|
||||
if [[ "$nvda2speechdStarted" == "true" ]]; then
|
||||
return
|
||||
fi
|
||||
if ! ss -ltnp | rg 3457 | grep -q 'cthulhu'; then
|
||||
if [[ -x "${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/nvda2speechd" ]]; then
|
||||
local translateSetting="${TRANSLATE:-unset}"
|
||||
local translateFromSetting="${TRANSLATE_FROM:-unset}"
|
||||
local translateToSetting="${TRANSLATE_TO:-unset}"
|
||||
log_msg "Preparing nvda2speechd with TRANSLATE=${translateSetting} TRANSLATE_FROM=${translateFromSetting} TRANSLATE_TO=${translateToSetting}."
|
||||
if [[ "${translateSetting,,}" == "true" ]] || [[ "$translateSetting" == "1" ]]; then
|
||||
if ! command -v trans &> /dev/null; then
|
||||
log_msg "TRANSLATE is enabled but 'trans' is missing; nvda2speechd may fail to start."
|
||||
fi
|
||||
fi
|
||||
"${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/nvda2speechd" &> /dev/null &
|
||||
nvda2speechdPid=$!
|
||||
nvda2speechdStarted="true"
|
||||
log_msg "Started nvda2speechd (pid ${nvda2speechdPid})."
|
||||
else
|
||||
log_msg "nvda2speechd binary not found or not executable; skipping start."
|
||||
fi
|
||||
else
|
||||
log_msg "cthulhu is already listening on port 3457; skipping nvda2speechd start."
|
||||
fi
|
||||
}
|
||||
|
||||
stop_nvda2speechd() {
|
||||
if [[ "$nvda2speechdStarted" != "true" ]]; then
|
||||
return
|
||||
fi
|
||||
if [[ -n "$nvda2speechdPid" ]] && kill -0 "$nvda2speechdPid" 2>/dev/null; then
|
||||
kill "$nvda2speechdPid" 2>/dev/null
|
||||
wait "$nvda2speechdPid" 2>/dev/null
|
||||
fi
|
||||
nvda2speechdPid=""
|
||||
nvda2speechdStarted="false"
|
||||
}
|
||||
|
||||
enable_cthulhu_window_title_reader() {
|
||||
if [[ "$cthulhuTitleReaderEnabled" == "true" ]]; then
|
||||
return 0
|
||||
fi
|
||||
if [[ "$cthulhuTitleReaderTried" == "true" ]]; then
|
||||
return 1
|
||||
fi
|
||||
cthulhuTitleReaderTried="true"
|
||||
|
||||
if ! command -v gdbus &> /dev/null; then
|
||||
log_msg "gdbus not found; cannot enable Cthulhu WindowTitleReader."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local dbusService="org.stormux.Cthulhu.Service"
|
||||
local modulePath="/org/stormux/Cthulhu/Service/PluginSystemManager"
|
||||
local titleModulePath="/org/stormux/Cthulhu/Service/Plugin_WindowTitleReader"
|
||||
local moduleInterface="org.stormux.Cthulhu.Module"
|
||||
local enableResult=""
|
||||
local titleEnableResult=""
|
||||
|
||||
gdbus call --session --dest "$dbusService" \
|
||||
--object-path "$modulePath" \
|
||||
--method "${moduleInterface}.ExecuteCommand" \
|
||||
"RescanPlugins" false &> /dev/null || true
|
||||
|
||||
enableResult="$(gdbus call --session --dest "$dbusService" \
|
||||
--object-path "$modulePath" \
|
||||
--method "${moduleInterface}.ExecuteParameterizedCommand" \
|
||||
"SetPluginActive" \
|
||||
'{"plugin_name": <"WindowTitleReader">, "active": <true>}' \
|
||||
false 2>/dev/null || true)"
|
||||
|
||||
if [[ "$enableResult" != *"true"* ]]; then
|
||||
log_msg "Failed to activate Cthulhu WindowTitleReader plugin via D-Bus."
|
||||
return 1
|
||||
fi
|
||||
|
||||
titleEnableResult="$(gdbus call --session --dest "$dbusService" \
|
||||
--object-path "$titleModulePath" \
|
||||
--method "${moduleInterface}.ExecuteParameterizedCommand" \
|
||||
"SetEnabled" \
|
||||
'{"enabled": <true>}' \
|
||||
false 2>/dev/null || true)"
|
||||
|
||||
if [[ "$titleEnableResult" == *"true"* ]]; then
|
||||
cthulhuTitleReaderEnabled="true"
|
||||
log_msg "Enabled Cthulhu WindowTitleReader tracking via D-Bus."
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_msg "Failed to enable Cthulhu WindowTitleReader tracking via D-Bus."
|
||||
return 1
|
||||
}
|
||||
|
||||
kill_nvda2speechd_listener() {
|
||||
local nvdaPids=()
|
||||
mapfile -t nvdaPids < <(pgrep -u "${USER}" -x nvda2speechd 2>/dev/null)
|
||||
if [[ ${#nvdaPids[@]} -eq 0 ]]; then
|
||||
log_msg "No nvda2speechd process found to stop."
|
||||
return
|
||||
fi
|
||||
log_msg "Stopping nvda2speechd process(es): ${nvdaPids[*]}."
|
||||
for pid in "${nvdaPids[@]}"; do
|
||||
kill "$pid" 2>/dev/null
|
||||
done
|
||||
local remainingPids=()
|
||||
mapfile -t remainingPids < <(pgrep -u "${USER}" -x nvda2speechd 2>/dev/null)
|
||||
if [[ ${#remainingPids[@]} -gt 0 ]]; then
|
||||
log_msg "nvda2speechd still running after stop attempt: ${remainingPids[*]}."
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup_and_exit() {
|
||||
stop_nvda2speechd
|
||||
}
|
||||
|
||||
# Check and manage wine32 installation
|
||||
check_wine32() {
|
||||
local wine32Dir="${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/wine32"
|
||||
@@ -316,27 +447,33 @@ kill_game() {
|
||||
# for games that require custom scripts before launch or custom launch parameters
|
||||
custom_launch_parameters() {
|
||||
if [[ "${game[2]}" == "Dragon Pong" ]]; then
|
||||
"${scriptDir}/speech/speak_window_title.sh" DragonPong.exe &
|
||||
if ! enable_cthulhu_window_title_reader; then
|
||||
"${scriptDir}/speech/speak_window_title.sh" DragonPong.exe &
|
||||
fi
|
||||
start_nvda2speechd
|
||||
pushd "$(winepath "$winePath")" || exit 1
|
||||
wine "$wineExec"
|
||||
popd || exit 1
|
||||
exit 0
|
||||
customLaunchHandled="true"
|
||||
return 0
|
||||
fi
|
||||
if [[ "${game[2]}" == "Dreamland" ]]; then
|
||||
"$WINE" "${game[1]}" &> /dev/null &
|
||||
exit 0
|
||||
start_nvda2speechd
|
||||
"$WINE" "${game[1]}" &> /dev/null
|
||||
customLaunchHandled="true"
|
||||
return 0
|
||||
fi
|
||||
# executioner's-rage: DLL replacement now handled by update_nvda_dlls()
|
||||
if [[ "${game[2]}" == "Laser Breakout" ]]; then
|
||||
"${scriptDir}/speech/speak_window_title.sh" play.exe &
|
||||
if ! enable_cthulhu_window_title_reader; then
|
||||
"${scriptDir}/speech/speak_window_title.sh" play.exe &
|
||||
fi
|
||||
fi
|
||||
if [[ "${game[2]}" == "Bokurano Daibouken 2" ]]; then
|
||||
find "${WINEPREFIX}/drive_c/nyanchangame/bk2" -type f -name 'nvdaControllerClient.dll' -exec rm -v "{}" \;
|
||||
"${scriptDir}/speech/clipboard_translator.sh" "play.exe" bokurano-daibouken2 &
|
||||
export TRANSLATE=true
|
||||
fi
|
||||
if [[ "${game[2]}" == "Bokurano Daibouken" ]]; then
|
||||
find "${WINEPREFIX}/drive_c/nyanchangame/bk" -type f -name 'nvdaControllerClient.dll' -exec rm -v "{}" \;
|
||||
"${scriptDir}/speech/clipboard_translator.sh" "play.exe" bokurano-daibouken &
|
||||
export TRANSLATE=true
|
||||
fi
|
||||
if [[ "${game[2]}" == "Bokurano Daibouken 3" ]]; then
|
||||
dictPath="$(winepath "${winePath}")"
|
||||
@@ -358,13 +495,19 @@ custom_launch_parameters() {
|
||||
fi
|
||||
fi
|
||||
if [[ "${game[2]}" == "Bop It Emulator" ]]; then
|
||||
"${scriptDir}/speech/speak_window_title.sh" bop.exe &
|
||||
if ! enable_cthulhu_window_title_reader; then
|
||||
"${scriptDir}/speech/speak_window_title.sh" bop.exe &
|
||||
fi
|
||||
fi
|
||||
if [[ "${game[2]}" == "Road to Rage" ]]; then
|
||||
"${scriptDir}/speech/speak_window_title.sh" trtr.exe &
|
||||
if ! enable_cthulhu_window_title_reader; then
|
||||
"${scriptDir}/speech/speak_window_title.sh" trtr.exe &
|
||||
fi
|
||||
fi
|
||||
if [[ "${game[2]}" == "Axel Pong" ]]; then
|
||||
"${scriptDir}/speech/speak_window_title.sh" axel_pong.exe &
|
||||
if ! enable_cthulhu_window_title_reader; then
|
||||
"${scriptDir}/speech/speak_window_title.sh" axel_pong.exe &
|
||||
fi
|
||||
fi
|
||||
if [[ "${game[2]}" == "Sequence Storm" ]]; then
|
||||
"${scriptDir}/speech/clipboard_reader.sh" SequenceStorm &
|
||||
@@ -375,30 +518,40 @@ custom_launch_parameters() {
|
||||
#fi
|
||||
# sketchbook: DLL replacement now handled by update_nvda_dlls()
|
||||
if [[ "${game[2]}" == "Audiodisc" ]]; then
|
||||
start_nvda2speechd
|
||||
wine "$winePath\\$wineExec"
|
||||
exit 0
|
||||
customLaunchHandled="true"
|
||||
return 0
|
||||
fi
|
||||
if [[ "${game[2]}" == "Audioquake" ]]; then
|
||||
start_nvda2speechd
|
||||
wine "$winePath\\$wineExec"
|
||||
exit 0
|
||||
customLaunchHandled="true"
|
||||
return 0
|
||||
fi
|
||||
if [[ "${game[2]}" == "Screaming Strike 2" ]]; then
|
||||
start_nvda2speechd
|
||||
pushd "$(winepath "$winePath")" || exit 1
|
||||
wine "$wineExec"
|
||||
popd || exit 1
|
||||
exit 0
|
||||
customLaunchHandled="true"
|
||||
return 0
|
||||
fi
|
||||
if [[ "${game[2]}" == "Warsim" ]]; then
|
||||
start_nvda2speechd
|
||||
pushd "$(winepath "${game[1]%\\*}")" || exit 1
|
||||
wine "${game[1]##*\\}"
|
||||
popd || exit 1
|
||||
exit 0
|
||||
customLaunchHandled="true"
|
||||
return 0
|
||||
fi
|
||||
if [[ "${game[2]}" == "Interceptor" ]]; then
|
||||
start_nvda2speechd
|
||||
pushd "$(winepath "$winePath")" || exit 1
|
||||
wine "$wineExec"
|
||||
popd || exit 1
|
||||
exit 0
|
||||
customLaunchHandled="true"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -474,14 +627,8 @@ game_launcher() {
|
||||
[[ "$agmNoLaunch" == "true" ]] && return
|
||||
# shellcheck source=.includes/bottle.sh
|
||||
source "${scriptDir}/.includes/bottle.sh"
|
||||
|
||||
# Start nvda2speechd if available
|
||||
if ! ss -ltnp | rg 3457 | grep -q 'cthulhu'; then
|
||||
if [[ -x "${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/nvda2speechd" ]]; then
|
||||
"${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/nvda2speechd" &> /dev/null &
|
||||
fi
|
||||
fi
|
||||
|
||||
# Ensure a clean nvda2speechd state before launching a new game.
|
||||
kill_nvda2speechd_listener
|
||||
# Replace NVDA controller client DLLs in wine64 bottle
|
||||
update_nvda_dlls
|
||||
mapfile -t lines < <(sed -e '/^$/d' -e '/^ *#/d' "${configFile}" 2> /dev/null | sort -t '|' -k3,3f)
|
||||
@@ -568,15 +715,22 @@ game_launcher() {
|
||||
fi
|
||||
fi
|
||||
process_launcher_flags
|
||||
customLaunchHandled="false"
|
||||
custom_launch_parameters
|
||||
if [[ "$debugGdb" == "1" ]]; then
|
||||
# Change to game directory before launching
|
||||
pushd "$(winepath "${game[1]%\\*}")" > /dev/null || exit 1
|
||||
winedbg --gdb "${game[1]##*\\}"
|
||||
popd > /dev/null || exit 1
|
||||
else
|
||||
wine start /d "${game[1]%\\*}" "${game[1]##*\\}" /realtime
|
||||
if [[ "$customLaunchHandled" == "true" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
start_nvda2speechd
|
||||
# Change to game directory before launching (required for proper game operation)
|
||||
pushd "$(winepath "${game[1]%\\*}")" > /dev/null || exit 1
|
||||
if [[ "$debugGdb" == "1" ]]; then
|
||||
winedbg --gdb "${game[1]##*\\}"
|
||||
else
|
||||
# Use direct wine execution instead of 'wine start' to ensure clipboard works
|
||||
# See: https://bugs.winehq.org/show_bug.cgi?id=50598
|
||||
wine "${game[1]##*\\}"
|
||||
fi
|
||||
popd > /dev/null || exit 1
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
@@ -584,10 +738,12 @@ game_launcher() {
|
||||
|
||||
# main script
|
||||
|
||||
trap "exit 0" SIGINT
|
||||
trap cleanup_and_exit EXIT
|
||||
trap "cleanup_and_exit; exit 0" SIGINT SIGTERM
|
||||
|
||||
# Detect dialog interface type BEFORE potentially setting DISPLAY
|
||||
# This must happen before we modify DISPLAY to preserve console detection
|
||||
# shellcheck disable=SC2034
|
||||
if [[ -z "$DISPLAY" ]]; then
|
||||
dialogType="dialog"
|
||||
elif command -v yad &> /dev/null; then
|
||||
|
||||
Reference in New Issue
Block a user