From de654bcbb720a2427e3d3625bd57ee63ae7c0ce7 Mon Sep 17 00:00:00 2001 From: Sander Land <48946947+sanderland@users.noreply.github.com> Date: Mon, 8 Jun 2026 09:15:17 +0200 Subject: [PATCH] v1.18.1: fix Windows/frozen-build startup crash (#824) (#825) Co-authored-by: Claude Opus 4.8 (1M context) --- katrain/core/constants.py | 2 +- katrain/gui/sound.py | 27 +++++++++++++++++---------- pyproject.toml | 6 +++++- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/katrain/core/constants.py b/katrain/core/constants.py index 6bec82a..6a674d4 100644 --- a/katrain/core/constants.py +++ b/katrain/core/constants.py @@ -1,5 +1,5 @@ PROGRAM_NAME = "KaTrain" -VERSION = "1.18.0" +VERSION = "1.18.1" HOMEPAGE = "https://github.com/sanderland/katrain" CONFIG_MIN_VERSION = "1.17.0" # keep config files from this version ANALYSIS_FORMAT_VERSION = "1.0" diff --git a/katrain/gui/sound.py b/katrain/gui/sound.py index 7150b46..8d7a34a 100644 --- a/katrain/gui/sound.py +++ b/katrain/gui/sound.py @@ -31,16 +31,23 @@ def preload_sounds(sound_dir): if not audio_files: return - # Test if audio subsystem works by loading one sound in a subprocess - try: - subprocess.run( - [sys.executable, "-c", - f"from kivy.core.audio import SoundLoader; SoundLoader.load({audio_files[0]!r})"], - timeout=3, capture_output=True, - ) - except subprocess.TimeoutExpired as e: - print(f"Warning: Audio unavailable ({e}). Sounds disabled.", file=sys.stderr) - return + # SoundLoader.load() deadlocks when no audio output device is available, so + # on macOS/Linux we first probe in a subprocess. We skip the probe when: + # - on Windows, where the deadlock does not occur, and + # - in frozen builds, where sys.executable is the katrain app (not python), + # so "-c " relaunches katrain instead of running the snippet; + # Kivy then misparses it as a "section:key:value" config arg and crashes. + # See https://github.com/sanderland/katrain/issues/824 + if platform != "win" and not getattr(sys, "frozen", False): + try: + subprocess.run( + [sys.executable, "-c", + f"from kivy.core.audio import SoundLoader; SoundLoader.load({audio_files[0]!r})"], + timeout=3, capture_output=True, + ) + except subprocess.TimeoutExpired as e: + print(f"Warning: Audio unavailable ({e}). Sounds disabled.", file=sys.stderr) + return # Audio works, preload all sounds for path in audio_files: diff --git a/pyproject.toml b/pyproject.toml index 005e113..2349ed3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,12 @@ [project] name = "KaTrain" -version = "1.18.0" +version = "1.18.1" description = "Go/Baduk/Weiqi playing and teaching app with a variety of AIs" authors = [{ name = "Sander Land" }] +# Cap tracks binary-wheel availability of kivy + ffpyplayer (no cp314 wheels yet). +# Kivy 3.14 support is merged to master but unreleased (kivy/kivy#9225); ffpyplayer +# 3.14 is still in progress (matham/ffpyplayer#185). Raise the cap once both ship +# cp314 wheels. Note ffpyplayer is our direct dep (audio); kivy does not pull it. requires-python = ">=3.10,<3.14" readme = "README.md" license = "MIT"