Skip to content

Fix wxPython 4.2 / wxWidgets 3.2 compatibility (resolves macOS 14+ crash)#127

Open
jdlondon wants to merge 5 commits into
belangeo:masterfrom
jdlondon:wxpython-42-compat
Open

Fix wxPython 4.2 / wxWidgets 3.2 compatibility (resolves macOS 14+ crash)#127
jdlondon wants to merge 5 commits into
belangeo:masterfrom
jdlondon:wxpython-42-compat

Conversation

@jdlondon
Copy link
Copy Markdown

Problem

The Cecilia5 5.4.1 download on the project page crashes immediately
after the splash screen on macOS 14 (Sonoma) and later with a segfault
inside libwx_osx_cocoau_core-3.1.4.0.0.dylib during
CGFunctionEvaluate. A native crash report shows the offending call is
in the CGShading callback
(wxMacCoreGraphicsPenBrushDataBase::CalculateShadingValues), which
receives a NULL info pointer on Sonoma's deferred display-list
renderer. The crash triggers on any gradient brush, and the Cecilia UI
uses gradients heavily (sliders, knobs, toggles, label triangles), so
it has no way to proceed. wxWidgets 3.2 handles the lifecycle
correctly.

Rebuilding against wxPython 4.2 / wxWidgets 3.2 avoids the crash but
exposes wxPython 4.2's stricter type checking for drawing-method
arguments (floats no longer silently coerced to int). Most such sites
were fixed on master by the 2021–2023 commits (655954e, 266d613,
14a27ef, 8e97a59), but a handful remain. Additionally,
wx.GraphicsContext_Create (underscored alias) was removed in
wxPython 4.2 and needs the dotted form.

Fixes (5 commits, each self-contained)

  1. Fix remaining float values in wxPython 4.2 drawing calls.
    13 call sites across CeciliaPlot.py, Sliders.py, Widgets.py,
    Control.py where Python 3 true division or arithmetic on float
    attributes produced floats. Fixed in place with int(...) wrappers
    or // division, matching the style established in commits
    14a27ef and 8e97a59. Includes the
    wx.Colour(knobcolor[0] * 0.25, ...) case at Sliders.py:1484,
    which parallels the * 0.35 fix already applied to the sibling
    RangeSlider.setFillColour on master.

  2. Replace wx.GraphicsContext_Create with wx.GraphicsContext.Create.
    26 occurrences across 5 files. The underscored alias was removed in
    wxPython 4.2; the dotted form has been available for many versions
    and is backwards-compatible.

  3. py2app: include pyo explicitly. pyo is imported
    conditionally in audio.py (pyo64 vs pyo based on sample precision),
    so py2app's static analyser misses it and omits it from the bundle.

  4. info.plist: target Python 3.11. Updates PyRuntimeLocations,
    PythonExecutable, and version strings from Python 2.7 stubs to
    3.11.

  5. builder_OSX.sh: target Python 3.11 / wxWidgets 3.2. Bumps
    install_name_tool paths from 3.1.4.0.03.2.0.4.2 dylibs and
    python3.7python3.11. Also fixes broken find -exec syntax
    (missing semicolons on the .git/.pyc cleanup lines) and narrows
    the hidden-file cleanup to only .DS_Store so it doesn't also
    strip .gitignore, __pycache__, etc. Adds a post-build step that
    flattens py2app's Contents/Resources/Resources/ nesting, because
    constants.py expects RESOURCES_PATH == Contents/Resources.

Testing

Built against Python 3.11.12 / wxPython 4.2.5 / wxWidgets 3.2.9 on
macOS 14.8.3. Verified with the bundled .app:

  • Default startup (random module): 30s runtime, zero errors.
  • AutoModFilter (range widget; previously crashed with
    NoneType.slider downstream from a wx.Colour(float) in
    buildGrapher): loads cleanly.
  • MultiBandDelay (csplitter path, exercises the Sliders.py:1484
    fix): loads cleanly.
  • One module from every category (Dynamics / Filters / Multiband /
    Pitch / Resonators&Verbs / Spectral / Synthesis / Time): all load
    cleanly.

Note on the binary release

I notice that the 5.4.1 version on the project site predates the more
recent drawing fixes, and the official macOS binary has the wx crash
on Sonoma and later. Hopefully the fixes in this PR are helpful if
you're considering a future updated release. I've left the version in
the builder script at 5.4.1 for now.


AI usage disclosure: some parts of this PR and its summary were
prepared and validated using Opus 4.6 and 4.7.

wxPython 4.2 is strict about integer coordinates for DC / GraphicsContext
methods. A number of call sites still produced floats via Python 3 true
division or arithmetic on float-valued attributes, and would crash with
TypeError on modern wxPython. Wrap the offending values in int() at the
call site, matching the pattern used in earlier fixes (commits 14a27ef
and 8e97a59).
The underscored alias was removed in wxPython 4.2. The dotted form
has been available for many versions and is backwards-compatible.
pyo is imported conditionally in audio.py (pyo64 vs pyo based on sample
precision), so py2app's static analyser does not pick it up and omits
it from the bundled app.
Python 2.7 is end-of-life; the bundled Python framework that py2app
deploys is 3.11, and PyRuntimeLocations / PythonExecutable keys need
to match, otherwise the app fails to locate the interpreter.
 - Bump Python from 3.7 to 3.11 (3.7 is EOL).
 - Bump bundled wxWidgets dylibs from 3.1.4.0.0 to 3.2.0.4.2; the 3.1.4
   CGShading callback crashes on macOS 14 Sonoma and later.
 - Fix broken find invocations (missing semicolons on -exec) and tighten
   the hidden-file cleanup to only remove .DS_Store (previous .* glob
   would also have removed __pycache__, .gitignore, etc.).
 - Flatten py2app's Resources/Resources/ nesting post-build so that
   constants.py's os.getcwd()-based RESOURCES_PATH resolves correctly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant