Create new _sdl3_mixer module#3753
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src_py/_sdl3_mixer.py (2)
34-43: Validatedevicebefore dereferencing_statefor clearer API errors.Right now invalid
deviceinput can raiseAttributeErrorinstead of a consistentTypeErrorfrom this wrapper.Proposed refactor
class Mixer(_sdl3_mixer_c.Mixer): @@ def __init__( self, device: audio.AudioDevice = audio.DEFAULT_PLAYBACK_DEVICE, spec: audio.AudioSpec | None = None, ) -> None: + if not isinstance(device, audio.AudioDevice): + raise TypeError( + "Mixer init 'device' argument must be an AudioDevice, " + f"received {type(device)}" + ) if spec is None: _sdl3_mixer_c.Mixer.__init__(self, device._state, spec)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src_py/_sdl3_mixer.py` around lines 34 - 43, Validate the incoming device before accessing device._state in Mixer.__init__ to provide a consistent TypeError for bad inputs: in __init__ check that device is an instance of audio.AudioDevice (or is audio.DEFAULT_PLAYBACK_DEVICE) and if not raise TypeError with a clear message, then call _sdl3_mixer_c.Mixer.__init__(self, device._state, ...) in both branches (the spec None branch and the spec instanceof audio.AudioSpec branch); ensure both paths perform the same device validation before dereferencing device._state.
109-114: Minor cleanup: collapse duplicatedset_audiostreamcall.Both valid branches call the same C method; this can be simplified without changing behavior.
Proposed cleanup
def set_audiostream(self, audiostream: audio.AudioStream | None) -> None: - if isinstance(audiostream, audio.AudioStream): - _sdl3_mixer_c.Track.set_audiostream(self, audiostream) - elif audiostream is None: + if isinstance(audiostream, audio.AudioStream) or audiostream is None: _sdl3_mixer_c.Track.set_audiostream(self, None) else: raise TypeError( "audiostream argument must be an AudioStream or None, " f"received {type(audiostream)}" )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src_py/_sdl3_mixer.py` around lines 109 - 114, Collapse the duplicate calls to _sdl3_mixer_c.Track.set_audiostream in Track.set_audiostream: instead of calling _sdl3_mixer_c.Track.set_audiostream(self, audiostream) in both the isinstance(audio.AudioStream) and audiostream is None branches, call _sdl3_mixer_c.Track.set_audiostream(self, audiostream) once; keep a simple type check to raise a TypeError for invalid values (non audio.AudioStream and non-None) so the function still validates input.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src_py/_sdl3_mixer.py`:
- Around line 34-43: Validate the incoming device before accessing device._state
in Mixer.__init__ to provide a consistent TypeError for bad inputs: in __init__
check that device is an instance of audio.AudioDevice (or is
audio.DEFAULT_PLAYBACK_DEVICE) and if not raise TypeError with a clear message,
then call _sdl3_mixer_c.Mixer.__init__(self, device._state, ...) in both
branches (the spec None branch and the spec instanceof audio.AudioSpec branch);
ensure both paths perform the same device validation before dereferencing
device._state.
- Around line 109-114: Collapse the duplicate calls to
_sdl3_mixer_c.Track.set_audiostream in Track.set_audiostream: instead of calling
_sdl3_mixer_c.Track.set_audiostream(self, audiostream) in both the
isinstance(audio.AudioStream) and audiostream is None branches, call
_sdl3_mixer_c.Track.set_audiostream(self, audiostream) once; keep a simple type
check to raise a TypeError for invalid values (non audio.AudioStream and
non-None) so the function still validates input.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4c36b424-34c6-4605-9e73-a1e7ac65a328
📒 Files selected for processing (1)
src_py/_sdl3_mixer.py
Supports SDL3 mixer constructs in close to their native form. Right now it's as a private module that only builds in SDL3. This is a stepping stone towards overall mixer support for SDL3 builds, with a compatibility layer exposing old API on top of the new, along with giving folks the new powerful stuff directly.
6375c3d to
0dde50f
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
src_c/_sdl3_mixer_c.c (2)
594-601: 💤 Low valueKnown
MIX_CreateSineWaveAudiobug — track upstream fix.The inline comment notes
MIX_CreateSineWaveAudiois bugged (invalid context parameter). Consider opening an upstream SDL3_mixer issue (or linking the existing one) and adding a TODO with a tracking link so this can be revisited and the user-facing error surfaced clearly until then.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src_c/_sdl3_mixer_c.c` around lines 594 - 601, The call to MIX_CreateSineWaveAudio (in the code path that assigns MIX_Audio *sine_wave_audio) is known to be bugged and currently hides user-facing context errors; open or link an upstream SDL3_mixer issue tracking this "invalid context parameter" bug and add a TODO comment next to the MIX_CreateSineWaveAudio call that includes the upstream issue URL/ID and a short note to revisit once patched, and update the error handling so the RAISE(pgExc_SDLError, SDL_GetError()) remains but the TODO clearly documents the upstream issue for future removal.
1527-1528: 💤 Low valueMinor: stale function name in comment.
The comment refers to
pg_audio_clear, but the function actually called ispg_mixer_clear. Likely a leftover from a rename.Proposed fix
- // allow pg_audio_exec to omit calling pg_audio_clear on error + // allow pg_audio_exec to omit calling pg_mixer_clear on error (void)pg_mixer_clear((PyObject *)module);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src_c/_sdl3_mixer_c.c` around lines 1527 - 1528, Update the stale comment to reference the correct function name: change the comment that currently mentions "pg_audio_clear" to "pg_mixer_clear" (the code calls pg_mixer_clear((PyObject *)module)); ensure the comment accurately explains that this allows pg_audio_exec to omit calling pg_mixer_clear on error, or replace the comment with a concise note about allowing pg_audio_exec to omit clearing on error.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src_c/_sdl3_mixer_c.c`:
- Around line 98-106: The code calls PyObject_GetAttrString(...) to fetch
_audio_type and immediately passes it to PyArg_ParseTupleAndKeywords with "O!"
which is unsafe if GetAttrString returned NULL; add a NULL check after each
PyObject_GetAttrString call (in this function and in pg_audio_obj_init,
pg_audio_obj_from_raw, pg_audio_obj_from_sine_wave, pg_track_obj_set_audio): if
the returned pointer is NULL, return NULL immediately (do not DECREF), otherwise
proceed to call PyArg_ParseTupleAndKeywords and only DECREF the acquired
audio_type after successful/failed parsing as appropriate.
- Around line 992-999: The SDL_IOStream returned by pgRWops_FromObject is not
closed when MIX_SetTrackIOStream(self->track, io, true) fails; modify the
failure path in the function handling the SDL_IOStream so that if
MIX_SetTrackIOStream(...) returns false you call SDL_CloseIO(io) before
returning the error via RAISE(pgExc_SDLError, SDL_GetError()), ensuring the
stream is freed when ownership was not transferred to SDL_mixer.
---
Nitpick comments:
In `@src_c/_sdl3_mixer_c.c`:
- Around line 594-601: The call to MIX_CreateSineWaveAudio (in the code path
that assigns MIX_Audio *sine_wave_audio) is known to be bugged and currently
hides user-facing context errors; open or link an upstream SDL3_mixer issue
tracking this "invalid context parameter" bug and add a TODO comment next to the
MIX_CreateSineWaveAudio call that includes the upstream issue URL/ID and a short
note to revisit once patched, and update the error handling so the
RAISE(pgExc_SDLError, SDL_GetError()) remains but the TODO clearly documents the
upstream issue for future removal.
- Around line 1527-1528: Update the stale comment to reference the correct
function name: change the comment that currently mentions "pg_audio_clear" to
"pg_mixer_clear" (the code calls pg_mixer_clear((PyObject *)module)); ensure the
comment accurately explains that this allows pg_audio_exec to omit calling
pg_mixer_clear on error, or replace the comment with a concise note about
allowing pg_audio_exec to omit clearing on error.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0264f656-682e-4f45-a354-70806aafc36c
📒 Files selected for processing (13)
.github/workflows/build-sdl3.ymlbuildconfig/download_win_prebuilt.pybuildconfig/stubs/meson.buildbuildconfig/stubs/mypy_allow_list.txtbuildconfig/stubs/pygame/_sdl3_mixer.pyidev.pymeson.buildsrc_c/_base_audio.csrc_c/_base_audio.hsrc_c/_sdl3_mixer_c.csrc_c/meson.buildsrc_py/_sdl3_mixer.pysrc_py/meson.build
💤 Files with no reviewable changes (1)
- dev.py
✅ Files skipped from review due to trivial changes (5)
- src_c/_base_audio.h
- buildconfig/stubs/mypy_allow_list.txt
- buildconfig/stubs/meson.build
- .github/workflows/build-sdl3.yml
- meson.build
🚧 Files skipped from review as they are similar to previous changes (5)
- src_py/meson.build
- src_c/meson.build
- src_c/_base_audio.c
- src_py/_sdl3_mixer.py
- buildconfig/stubs/pygame/_sdl3_mixer.pyi
Supports SDL3 mixer constructs in close to their native form. Right now it's as a private module that only builds in SDL3. This is a stepping stone towards overall mixer support for SDL3 builds, with a compatibility layer exposing old API on top of the new, along with giving folks the new powerful stuff directly.
Follow up PR after #3657 in the #3581 mega issue.
This was originally at #3692, but with so many AI reviews and merge conflicts, wanted to start fresh at a new location for ease of more review :).
Rough testing script: