Fixed speech-dispatcher library in Play Palace.
This commit is contained in:
@@ -71,6 +71,7 @@ python3 .codex/skills/linux-game-manager-dev/scripts/audit_game_catalog.py
|
|||||||
|
|
||||||
- Mismatched `.install/<Game>.sh` vs `.launch/<Game>.game` names create orphaned or invisible entries.
|
- Mismatched `.install/<Game>.sh` vs `.launch/<Game>.game` names create orphaned or invisible entries.
|
||||||
- Missing `installPath` reference in launcher prevents full uninstall.
|
- Missing `installPath` reference in launcher prevents full uninstall.
|
||||||
|
- `game_removal` parses the first `installPath` match in launcher text, so comments containing `installPath` can break removal path detection.
|
||||||
- Missing `run_update()` in `.update` scripts breaks update flow.
|
- Missing `run_update()` in `.update` scripts breaks update flow.
|
||||||
- Bypassing shared download helpers risks cache and validation regressions.
|
- Bypassing shared download helpers risks cache and validation regressions.
|
||||||
- For `uv`-based Python games that use `accessible-output2`, include a host copy of `libspeechd.so.2` and export `LD_LIBRARY_PATH` from the launcher to avoid distro packaging differences.
|
- For `uv`-based Python games that need `speechd`, copy host Python `speechd` bindings into a game-local directory and export `PYTHONPATH` from the launcher.
|
||||||
|
|||||||
@@ -108,27 +108,24 @@ python3 .codex/skills/linux-game-manager-dev/scripts/audit_game_catalog.py
|
|||||||
- For edited bash scripts, run shellcheck and fix all errors.
|
- For edited bash scripts, run shellcheck and fix all errors.
|
||||||
- If `shellcheck` is not installed, prompt the user to install it first (see `references/tooling-prereqs.md`).
|
- If `shellcheck` is not installed, prompt the user to install it first (see `references/tooling-prereqs.md`).
|
||||||
|
|
||||||
## Pattern: uv + Speech Dispatcher Host Libraries
|
## Pattern: uv + Host Python speechd Bindings
|
||||||
|
|
||||||
Use this pattern for Python games installed with `uv` when runtime speech support depends on system `libspeechd`.
|
Use this pattern for Python games installed with `uv` when runtime speech support depends on `import speechd`.
|
||||||
|
|
||||||
1. In installer script:
|
1. In installer script:
|
||||||
- Check dependencies: `git` and `uv`.
|
- Check dependencies: `git`, `uv`, and host python binding import (`python-speechd:speechd`).
|
||||||
- Clone game repository into `${installPath}/<GameRepoDir>`.
|
- Clone game repository into `${installPath}/<GameRepoDir>`.
|
||||||
- Run `uv sync` in the project directory that contains `pyproject.toml`.
|
- Run `uv sync` in the project directory that contains `pyproject.toml`.
|
||||||
- Locate `libspeechd.so.2` from host system using:
|
- Resolve speechd source path from host Python via:
|
||||||
- `ldconfig -p` when available.
|
- `python3 -c 'import pathlib,speechd; print(pathlib.Path(speechd.__file__).resolve())'`
|
||||||
- Fallback paths for common distros:
|
- Copy the module/package into a game-local directory such as:
|
||||||
- `/usr/lib/libspeechd.so.2` (Arch-style)
|
- `${installPath}/<GameRepoDir>/<RuntimePath>/.host-python/`
|
||||||
- `/usr/lib/x86_64-linux-gnu/libspeechd.so.2` (Debian/Ubuntu-style)
|
- Fail with a clear message if import or copy fails.
|
||||||
- `/usr/lib64/libspeechd.so.2` and related `/lib*` fallbacks
|
|
||||||
- Copy resolved library into a game-local directory such as:
|
|
||||||
- `${installPath}/<GameRepoDir>/<RuntimePath>/.host-libs/libspeechd.so.2`
|
|
||||||
- Fail with a clear message if library is not found.
|
|
||||||
|
|
||||||
2. In launcher script:
|
2. In launcher script:
|
||||||
- Export `LD_LIBRARY_PATH` with the game-local `.host-libs` directory prepended.
|
- Export `PYTHONPATH` with the game-local `.host-python` directory prepended.
|
||||||
- Launch via `uv run ...` from the same directory used for `uv sync`.
|
- Launch via `uv run ...` from the same directory used for `uv sync`.
|
||||||
|
|
||||||
3. Removal safety:
|
3. Removal safety:
|
||||||
- Ensure first `installPath` line in launcher points to a path that lets `game_removal` infer the game root correctly.
|
- Ensure first `installPath` line in launcher points to a path that lets `game_removal` infer the game root correctly.
|
||||||
|
- Do not put `installPath` in comments above that path line, because removal currently grabs the first matching line.
|
||||||
|
|||||||
+30
-30
@@ -1,17 +1,11 @@
|
|||||||
check_dependencies git uv
|
check_dependencies git uv python-speechd:speechd
|
||||||
|
|
||||||
# shellcheck disable=SC2154 # installPath is exported by linux-game-manager.sh
|
# shellcheck disable=SC2154 # set by linux-game-manager.sh
|
||||||
gameRoot="${installPath}/PlayPalace11"
|
gameRoot="${installPath}/PlayPalace11"
|
||||||
desktopPath="${gameRoot}/clients/desktop"
|
desktopPath="${gameRoot}/clients/desktop"
|
||||||
hostLibDir="${desktopPath}/.host-libs"
|
hostPythonDir="${desktopPath}/.host-python"
|
||||||
speechdLibPath=""
|
speechdFilePath=""
|
||||||
libCandidates=(
|
speechdCopySourcePath=""
|
||||||
"/usr/lib/libspeechd.so.2"
|
|
||||||
"/usr/lib64/libspeechd.so.2"
|
|
||||||
"/usr/lib/x86_64-linux-gnu/libspeechd.so.2"
|
|
||||||
"/lib/x86_64-linux-gnu/libspeechd.so.2"
|
|
||||||
"/lib64/libspeechd.so.2"
|
|
||||||
)
|
|
||||||
|
|
||||||
if [[ -e "${gameRoot}" ]]; then
|
if [[ -e "${gameRoot}" ]]; then
|
||||||
ui_msgbox "Game Installer" "Game Installer" "\"${gameRoot}\" already exists. Remove it first or choose a different game."
|
ui_msgbox "Game Installer" "Game Installer" "\"${gameRoot}\" already exists. Remove it first or choose a different game."
|
||||||
@@ -40,30 +34,36 @@ if ! uv sync; then
|
|||||||
fi
|
fi
|
||||||
popd > /dev/null || exit 1
|
popd > /dev/null || exit 1
|
||||||
|
|
||||||
if command -v ldconfig > /dev/null 2>&1; then
|
speechdFilePath="$(python3 -c 'import pathlib,speechd; print(pathlib.Path(speechd.__file__).resolve())' 2> /dev/null)"
|
||||||
speechdLibPath="$(ldconfig -p 2> /dev/null | awk '/libspeechd\.so\.2/{print $NF; exit}')"
|
if [[ -z "${speechdFilePath}" ]]; then
|
||||||
fi
|
ui_msgbox "Game Installer" "Game Installer" "Could not import python module speechd from host Python.\nInstall speech-dispatcher python bindings and try again."
|
||||||
|
|
||||||
if [[ -z "${speechdLibPath}" ]]; then
|
|
||||||
for libPath in "${libCandidates[@]}"; do
|
|
||||||
if [[ -r "${libPath}" ]]; then
|
|
||||||
speechdLibPath="${libPath}"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "${speechdLibPath}" ]]; then
|
|
||||||
ui_msgbox "Game Installer" "Game Installer" "Could not find libspeechd.so.2.\nInstall speech-dispatcher (Arch) or a libspeechd package (Debian/Ubuntu) and try again."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "${hostLibDir}" || {
|
if [[ "${speechdFilePath##*/}" == "__init__.py" ]]; then
|
||||||
ui_msgbox "Game Installer" "Game Installer" "Could not create ${hostLibDir}."
|
speechdCopySourcePath="${speechdFilePath%/*}"
|
||||||
|
elif [[ "${speechdFilePath##*/}" == "speechd.py" ]]; then
|
||||||
|
speechdCopySourcePath="${speechdFilePath}"
|
||||||
|
else
|
||||||
|
speechdCopySourcePath="${speechdFilePath}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ -r "${speechdCopySourcePath}" ]]; then
|
||||||
|
ui_msgbox "Game Installer" "Game Installer" "Could not read speechd python binding at ${speechdCopySourcePath}."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${hostPythonDir}" || {
|
||||||
|
ui_msgbox "Game Installer" "Game Installer" "Could not create ${hostPythonDir}."
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if ! cp -Lf "${speechdLibPath}" "${hostLibDir}/libspeechd.so.2"; then
|
if [[ -d "${speechdCopySourcePath}" ]]; then
|
||||||
ui_msgbox "Game Installer" "Game Installer" "Could not copy ${speechdLibPath} into ${hostLibDir}."
|
if ! cp -a "${speechdCopySourcePath}" "${hostPythonDir}/"; then
|
||||||
|
ui_msgbox "Game Installer" "Game Installer" "Could not copy speechd package into ${hostPythonDir}."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
elif ! cp -a "${speechdCopySourcePath}" "${hostPythonDir}/speechd.py"; then
|
||||||
|
ui_msgbox "Game Installer" "Game Installer" "Could not copy speechd module into ${hostPythonDir}."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
check_dependencies uv
|
check_dependencies uv
|
||||||
|
|
||||||
# shellcheck disable=SC2154 # installPath is exported by linux-game-manager.sh
|
# shellcheck disable=SC2154 # set by linux-game-manager.sh
|
||||||
gamePath="${installPath}/PlayPalace11/clients"
|
gamePath="${installPath}/PlayPalace11/clients"
|
||||||
desktopPath="${gamePath}/desktop"
|
desktopPath="${gamePath}/desktop"
|
||||||
hostLibDir="${desktopPath}/.host-libs"
|
hostPythonDir="${desktopPath}/.host-python"
|
||||||
|
|
||||||
if ! [[ -d "${desktopPath}" ]]; then
|
if ! [[ -d "${desktopPath}" ]]; then
|
||||||
ui_msgbox "Linux Game Manager" "Linux Game Manager" "Play Palace is not installed at ${desktopPath}."
|
ui_msgbox "Linux Game Manager" "Linux Game Manager" "Play Palace is not installed at ${desktopPath}."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -d "${hostLibDir}" ]]; then
|
if [[ -d "${hostPythonDir}" ]]; then
|
||||||
export LD_LIBRARY_PATH="${hostLibDir}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
|
export PYTHONPATH="${hostPythonDir}${PYTHONPATH:+:${PYTHONPATH}}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pushd "${desktopPath}" || exit 1
|
pushd "${desktopPath}" || exit 1
|
||||||
|
|||||||
Reference in New Issue
Block a user