Skip to content

Update to projectM v4.x (another try)#137

Merged
AlwinEsch merged 13 commits into
xbmc:Piersfrom
AlwinEsch:Piers-Dev
Jul 1, 2026
Merged

Update to projectM v4.x (another try)#137
AlwinEsch merged 13 commits into
xbmc:Piersfrom
AlwinEsch:Piers-Dev

Conversation

@AlwinEsch

Copy link
Copy Markdown
Member

No description provided.

@kodiai

kodiai Bot commented Apr 26, 2026

Copy link
Copy Markdown
Kodiai Review Summary

What Changed

Updates visualization.projectm to use projectM v4.x API, replacing the old C++ API with new C-style API functions and playlist management. Requested minimal review; timeout risk auto-reduced the effective review to minimal and covered 50/4286 changed files via large-PR triage (30 full, 20 abbreviated; 4236 not reviewed).

Reviewed: core logic

Strengths

  • ✅ Proper null pointer checks added throughout for m_projectM and m_playlist before use (src/Main.cpp:134, 142, 148, 181, 200, 210, 221, 232, 245, 258, 284, 298, 323)
  • ✅ Thread safety maintained with mutex locks protecting all projectM API calls in public methods

Observations

Impact

[MAJOR] src/Main.cpp (282, 284-286): Redundant function call and unused variable in GetActivePreset()
The function calls projectm_playlist_get_position() twice when the position is non-zero, and declares an unused variable preset. The condition on line 284 uses the position value as a boolean, causing wasteful double calls.

[MAJOR] src/Main.cpp (98-103, 350, 354, 374): Type mismatch between constructor and SetSetting()
Constructor uses GetSettingInt() for "smooth_duration", "preset_duration", and "beat_sens" settings, but SetSetting() uses GetFloat() for the same settings. This inconsistency causes different value types to be loaded at startup versus when settings are changed at runtime.

Verdict

🔴 Address before merging -- 2 blocking issue(s) found

  • Keyword parsing: No keywords detected
Review Details
  • Files reviewed: 4286

  • Findings: 0 critical, 4 major, 0 medium, 0 minor (includes 2 from summary observations)

  • Lines changed: +841275 -2454

  • Requested profile: minimal (auto, lines changed: 843729)

  • Effective profile: minimal

  • Bounded review: covered 50/4286 changed files via large-PR triage (30 full, 20 abbreviated; 4236 not reviewed)

  • Timeout auto-reduction: applied

  • Contributor experience: profile-backed (using linked contributor profile guidance)

  • Review completed: 2026-04-26T15:39:38.769Z

  • Total wall-clock: 4m 15s

  • Phase timings:

    • queue wait: 0ms
    • workspace preparation: 2.2s
    • retrieval/context assembly: 9.1s
    • executor handoff: 4.3s
    • remote runtime: 3m 57s
    • publication: 1.2s
  • Tokens: 8,878 in / 9,455 out | 0.4243

  • Review scope: Reviewed 50/4286 files, prioritized by risk

  • Full review: 30 files | Abbreviated review: 20 files | Not reviewed: 4236 files

Files not fully reviewed (sorted by risk score)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_200/shifter - mandala.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_mischa_collection/86.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_mischa_collection/EoS + Phat - chasers 11 sentinel C_poltergeist_mix response daemon.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_mischa_collection/EoS - glowsticks v2 05 and proton lights (+Krash's beat code) _Phat_remix07 recursive demons.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_mischa_collection/Fumbling_Foo & Flexi, Martin, Orb, Unchained - Harmony Nova v2a.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_mischa_collection/LuxXx - Makes Me Cry (five) (Makes Me Cry, So Lick My Tears, And Get Real High).milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_mischa_collection/Tripgnosis - Antimatter Streams.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_mischa_collection/raron, martin + flexi - squatting.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_projectM/Mstress & Juppy - Dancers In The Dark.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_stock/EoS + Phat - chasers 18 hallway.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_stock/EoS - glowsticks v2 05 and proton lights (+Krash's beat code) _Phat_remix02b.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_stock/EoS - glowsticks v2 05 and proton lights (+Krash's beat code) _Phat_remix07 recursive demons.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_stock/EoS - repeater 05 - rave on acid.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_stock/EoS - repeater 15 - kaleidoscope b.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_stock/Mstress & Juppy - Dancers In The Dark.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/86.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/AdamFX 2 Geiss - Mash-Up - Angelic Staine Glass Chapters 6.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/AdamFX 2 Geiss - Mash-Up - Angelic Staine Glass Chapters 6_1.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/AdamFX 2 Geiss - Mash-Up Sphere Xibit Graffiti Warp me Tydye7.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/An AdamFX n Martin Infusion 2 flexi - Why The Sky Looks Diffrent Today - AdamFx n Martin Infusion - Tack Tile Disfunction B.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/Bdrv EoS + Redi Jedi - frequency analysis + glowsticks - glow - o - scope male left handed complement BDRV et AL rmx2.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EOE125~1.MILk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS + Phat - chasers 11 sentinel C_poltergeist_mix response daemon.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS + Phat - chasers 12 sentinel Daemon - mash0000 - multi-band time-distortion aurora granules.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS + Phat - chasers 14 sentinel 616.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS + Phat - chasers 18 hallway.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS + Phat - chasers 19 Portal.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS + flexi - glowsticks v2 05 and proton lights (+Krash's beat code) _Phat_remix02b + illumination (Stahl's Mix).milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS + phat - chasers 11 sentinel c (jelly v4.x).milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS - glowsticks v2 03 music shifter edit b (Jelly V2).milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS - glowsticks v2 03 music shifter edit b (Stahl's Reactive RMX V2i2 - feat. flexi + phat).milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS - glowsticks v2 05 and proton lights (+Krash's beat code) _Phat_remix02b.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS - glowsticks v2 05 and proton lights (+Krash's beat code) _Phat_remix03 madhatter_v2.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS - glowsticks v2 05 and proton lights (+Krash's beat code) _Phat_remix07 recursive demons.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS - repeater 05 - rave on acid.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/EoS - repeater 15 - kaleidoscope b.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/Flexi - 100% shader fractal [origami edit].milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/Flexi - intensive shader fractal [suksma comp shader mix].milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/Flexi - intensive shader fractal.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/Flexi - mindblob [where it's at now] gno sth air fetch.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/Flexi - supersonic.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/LuX - Life's Game 1.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/LuxXx - Makes Me Cry (five) (Makes Me Cry, So Lick My Tears, And Get Real High).milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/LuxXx - StickVerse II.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/LuxXx - Stickflower II.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/Mstress & Juppy - Dancers In The Dark.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/ORB - Depth Charge 2.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/Stahlregen & EoS + Geiss + ORB + Phat - Fruitsticks (Flexi-Tex Shader).milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/Tripgnosis - Antimatter Streams.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/Tripgnosis - Negative Photon Burn.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/_Mig_085.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/beta106S + Phat - sentinel linearity b nz+ mbinistre ov mbajiq.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/ech0 - liquid firesticks I.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/flexi + cope - i blew you a soap bubble now what - feel the projection you are, connected to it all nz+ wrepwrimindloss w8.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/flexi + geiss - infused with the spiral (Heavy Oil Mix) nz+ rapery.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/flexi - lorenz chaser [accidental shader-lock mashup] (ripples)2 nz+ discombobule lose.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/martin - fresco flash - cainlien.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/schglasmia - danqueer.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_tryptonaut/suksma - flexi - lorenz chaser - heretical tribal necklace.milk (risk: 55)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/EoS + Geiss - glowsticks v2 03 music shifter edit b (water mix).milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/EoS + Phat - cubetrace - v2.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/EoS - glowsticks v2 03 music shifter edit b.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/EoS - glowsticks v2 03 music.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/EoS - glowsticks v2 04 music minimal.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/EoS and PieturP - AlienSpaceshipInvasion 2.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/Flexi - smashing fractals 2-0.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/ORB - Supernova Meltdown.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/shifter - cellular_Phat_YAK_Infusion_v2.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/yin - 290 - Sonic brainstorm.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/yin - 300 - Daydreamer.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/yin - 302 - Daydreamer (remix 2).milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_bltc201/yin - 317 - Ocean of Light (y remix).milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_eyetune/Martin N AdamFX Infusion = Phat+Yin+EoS_Mandala Chaser Ft AdamFX n Martin - The Beast Mandala Chaser FX H.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_eyetune/New Creation Sensation - AdamFx,Flexi,Amandio c n Martin - Star to Another World ft Hexocollie n Shadow Harlequin n Geiss B.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_eyetune/ORB - Mega Spectrum.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_eyetune/ORB - Nova Sunrise.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/A.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/EoS + Phat - chasers 08 nematode_Teal_mix.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/EoS + Phat - cubetrace - v2.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/EoS - glowsticks v2 03 music.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/EoS - glowsticks v2 04 music minimal.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/EoS 3d-glasses.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/EoS_Phat Whale_soul-monitor danger - music.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/Redi Jedi - triptacular to the max(maxtacular to the trip remix).milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/Studio Music - Intuitive Awareness (Traces of Love mix).milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/Studio Music - Intuitive Awareness (stimulus effect mix) .milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/Studio Music and Redi Jedi - Passionate Behavior.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/Studio Music and Redi Jedi - Shimmering Love (remix).milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/shifter - cellular_Phat_Spinny_Slide_mix_v2_Time_Mod_tan.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/shifter - cellular_Phat_Spinny_Swimmer_mix_v2.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/shifter - cellular_Phat_YAK_Infusion_v2.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/shifter - deep sea hydra spectrum.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/shifter - fuzzball.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/shifter - glassworms flare.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/yin + Phat + EoS - Dreams of Blood.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/yin - 280 - Coming home.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/yin - 290 - Sonic brainstorm.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/yin - 300 - Daydreamer.milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/yin - 302 - Daydreamer (remix 2).milk (risk: 54)
  • visualization.projectm/resources/projectM/presets/presets_milkdrop_104/yin - 317 - Ocean of Light (y remix).milk (risk: 54)
  • ...and 4136 more files
- Keyword parsing: No keywords detected

Comment thread src/Main.cpp Outdated
Comment thread src/Main.cpp Outdated
@AlwinEsch

Copy link
Copy Markdown
Member Author

@kodiai review this please

@kodiai

kodiai Bot commented Apr 27, 2026

Copy link
Copy Markdown
Kodiai Review Summary

What Changed

Migration from projectM v3 C++ API to v4 C API, replacing class-based calls with C-style function calls and introducing playlist management.

Reviewed: core logic, docs

Strengths

  • ✅ Proper resource cleanup with null checks in destructor (src/Main.cpp:157-167)
  • ✅ Consistent mutex protection for projectM instance access across all public methods (src/Main.cpp:195, 207, 216, etc.)
  • ✅ Memory leak prevention with projectm_playlist_free_string_array after allocating playlist items (src/Main.cpp:289)

Observations

Impact

[CRITICAL] src/Main.cpp (100-102): Dangling pointer in texture path setup
Local variable texturePath goes out of scope at the end of the constructor, but a pointer to its internal buffer is passed to projectm_set_texture_search_paths. If the library stores the pointer instead of copying the string data, this causes a use-after-free when the library later attempts to access texture paths.

[MAJOR] src/Main.cpp (469-473): Failed reinitialization leaves object in broken state
If InitProjectM() fails during beat sensitivity change, the function returns ADDON_STATUS_UNKNOWN but leaves m_projectM null and m_playlist disconnected (disconnected at line 493, never reconnected). Subsequent visualization operations will silently fail, leaving the add-on non-functional until restart.

[MEDIUM] src/Main.cpp (608-612): PresetSwitchedEvent callback lacks defensive validation
Callback PresetSwitchedEvent dereferences the context pointer and accesses m_playlist without null checks. While the playlist library should manage callback lifecycle correctly, defensive null checks would prevent crashes if the callback is invoked during unexpected states.

Suggestions

  • Optional: Store texture path in a member variable to guarantee lifetime, or add a comment confirming that projectm_set_texture_search_paths copies the string data
  • Optional: Add recovery logic in InitProjectM to restore previous state if reinitialization fails, or add diagnostic logging for broken state

Verdict

🔴 Address before merging -- 2 blocking issue(s) found (CRITICAL/MAJOR)

Comment thread src/Main.cpp Outdated
Comment thread src/Main.cpp
Comment thread src/Main.cpp
@AlwinEsch

Copy link
Copy Markdown
Member Author

@kodiai review this please

@kodiai

kodiai Bot commented Apr 27, 2026

Copy link
Copy Markdown
Kodiai Review Summary

What Changed

Migration from projectM v3 to v4.x API, refactoring from C++ object-oriented API to C-style handle-based API.

Reviewed: core logic, docs

Strengths

  • ✅ Proper resource management with explicit cleanup of projectM and playlist handles in destructor (src/Main.cpp:160-170)
  • ✅ Consistent null pointer checks throughout all API methods to handle initialization failures safely

Observations

Impact

[MAJOR] src/Main.cpp (178, 201): Incomplete audio channel handling
The channels parameter from Start() is not stored or used (line 178 TODO comment), and AudioData() unconditionally uses PROJECTM_STEREO (line 201). This causes incorrect audio processing for mono sources, where iAudioDataLength/2 and PROJECTM_STEREO assumptions will misinterpret the audio buffer, potentially causing visualization artifacts or incorrect beat detection.

Suggestions

  • Optional: Consider storing the channels parameter in m_settings and using it to select between PROJECTM_MONO and PROJECTM_STEREO in AudioData()

Verdict

🔴 Address before merging -- 1 blocking issue(s) found

Comment thread src/Main.cpp Outdated
@AlwinEsch

Copy link
Copy Markdown
Member Author

@kodiai review this please

@kodiai

kodiai Bot commented Apr 27, 2026

Copy link
Copy Markdown
Kodiai Review Summary

What Changed

Major update from projectM v3.x to v4.x API, migrating from C++ class-based API to C handle-based API with separate playlist management. Reviewed: core logic, docs

Strengths

  • ✅ Comprehensive mutex protection added for thread-safe access to projectM resources (src/Main.cpp:208, 221, 230, etc.)
  • ✅ Proper resource cleanup with explicit null checks and destroy calls replacing raw delete (src/Main.cpp:161-170)
  • ✅ Audio data handling correctly accounts for channel count by dividing buffer length (src/Main.cpp:211)

Observations

Impact

[MAJOR] src/Main.cpp (138-171): Destructor lacks mutex protection for shared resources
Race condition: destructor accesses and destroys m_playlist and m_projectM without acquiring m_pmMutex, while other threads (Render, AudioData, etc.) may be holding the lock and using these pointers concurrently.

[MAJOR] src/Main.cpp (294): Missing null check for C API return value
projectm_playlist_items() return value is dereferenced without null check - causes crash if allocation fails or playlist is empty.

[MAJOR] src/Main.cpp (624-633): Race condition in callback during shutdown
PresetSwitchedEvent callback doesn't check m_shutdown flag before accessing m_playlist, which could be destroyed concurrently by destructor.

[MEDIUM] src/Main.cpp (211): Missing validation for channel count
Division by zero if Start() is called with channels == 0 - no validation before dividing iAudioDataLength / m_playedChannelAmount.

[MEDIUM] src/Main.cpp (446-459): Logic error in user preset folder handling
Line 452 sets m_settings.last_preset_folder unconditionally before calling ChooseUserPresetFolder(), bypassing the m_UserPackFolder check in that function when it's false.

Preference

[MINOR] src/Main.cpp (639): Unused variable
Optional: Remove unused thisClass variable in ProjectMLogCallback or use it for future logging enhancements.

Suggestions

  • Optional: Consider adding validation in Start() to reject invalid channel counts (< 1 or > max supported)
  • Future consideration: Add integration tests for the playlist callback lifecycle to verify thread safety during shutdown

Verdict

🔴 Address before merging -- 3 blocking issue(s) found (CRITICAL/MAJOR)

Comment thread src/Main.cpp Outdated
Comment thread src/Main.cpp
Comment thread src/Main.cpp
Comment thread src/Main.cpp
Comment thread src/Main.cpp
Comment thread src/Main.cpp Outdated
@AlwinEsch

Copy link
Copy Markdown
Member Author

@kodiai review this please

@kodiai

kodiai Bot commented Apr 27, 2026

Copy link
Copy Markdown
Kodiai Review Summary

What Changed

This PR updates the visualization.projectm addon from v3.1.12 to v4.x, migrating from the C++ API to the new C API with significant refactoring of initialization, playlist management, and settings handling.

Reviewed: core logic, C++ source changes

Strengths

  • ✅ Proper mutex usage throughout for thread safety in public functions (src/Main.cpp)
  • ✅ Good error handling with null pointer checks in most public functions (src/Main.cpp)
  • ✅ Proper resource cleanup in destructor with RAII patterns (src/Main.cpp:163-173)

Observations

Impact

[MAJOR] src/Main.cpp (201): InitProjectM() return value not checked on Windows
On Windows, InitProjectM() is called without checking the return value. If initialization fails, the visualization will be broken but Start() returns true, misleading callers about the actual state.

[MAJOR] src/Main.cpp (644-647): Race condition in PresetSwitchedEvent callback
The callback accesses m_playlist without holding the mutex. While m_shutdown is checked, there's a time-of-check-time-of-use race: if the callback passes the null check at line 644, the destructor could destroy m_playlist before line 647 executes, causing use-after-free.

Verdict

🔴 Address before merging -- 2 blocking issue(s) found

Comment thread src/Main.cpp Outdated
Comment thread src/Main.cpp
@AlwinEsch

Copy link
Copy Markdown
Member Author

@kodiai review this please

@kodiai

kodiai Bot commented Apr 27, 2026

Copy link
Copy Markdown
Kodiai Review Summary

What Changed

This PR updates the visualization addon from projectM v3 to v4, migrating to the new C API, reorganizing settings into a structured format, and including preset files.

Reviewed: core logic, docs

Strengths

  • ✅ Thread safety properly maintained with mutex protection across all projectM API calls (src/Main.cpp:234, 247, 256)
  • ✅ Good defensive null checks before using m_projectM and m_playlist in all public methods (src/Main.cpp:235-239, 248-251, 257-260)

Observations

Impact

[CRITICAL] src/Main.cpp (96-142): Constructor leaves object in invalid state if initialization fails
If InitProjectM() fails on line 96, the constructor returns early on line 98, leaving m_projectM and m_playlist as null pointers. The object exists but is unusable, causing crashes when any method is called. Consider setting a failure flag and checking it in all methods, or throwing an exception.

[MAJOR] src/Main.cpp (439): Type mismatch for smooth_duration setting
Setting is loaded as float in constructor (line 85: GetSettingFloat) but retrieved as int here (line 439: GetInt). This causes the setting to never match when changed, preventing updates from taking effect.

[MAJOR] src/Main.cpp (451): Type mismatch for preset_duration setting
Setting is loaded as float in constructor (line 86: GetSettingFloat) but retrieved as int here (line 451: GetInt). This causes the setting to never match when changed, preventing updates from taking effect.

[MAJOR] src/Main.cpp (493): Type mismatch for beat_sens setting
Setting is loaded as float in constructor (line 87: GetSettingFloat) but retrieved as int here (line 493: GetInt). This causes the setting to never match when changed, preventing updates from taking effect.

[MAJOR] src/Main.cpp (478): Wrong variable compared in user_preset_folder handler
Compares m_settings.last_preset_folder against newValue instead of m_settings.user_preset_folder. This causes the condition to evaluate incorrectly, potentially preventing user preset folder changes from being applied.

Suggestions

  • Optional: Consider extracting GetBasename() to use string_view for better performance when processing large preset lists
  • Future consideration: Add validation in InitProjectM() to verify preset folder exists before attempting to load

Verdict

🔴 Address before merging -- 5 blocking issue(s) found (CRITICAL/MAJOR)

AlwinEsch added 7 commits May 31, 2026 11:06
Relates to comming changes.

As the AI becomes not happy about comming "CVisualizationProjectM::PresetSwitchedEvent" without mutex, becomes it required to
have a recursive_mutex as this callback function becomes called from main thread with CVisualizationProjectM::Render as base
and where his called ProjectM function calls the callback on add-on.

Without freeze the add-on and Kodi no more usable.
During tests before was "mutex" two times called from main thread and one time from audio thread by "AudioData" call.
…lue)"

Before was about needed preset URL every ID checked with a "switch (pvalue)".

This now adds a map where makes more easy and smaller for changes in case used presets becomes updated in future.
This done to have easier an overview what comes from add-on settings.
Further are the names and the flow equal to settings.xml.
NOTE: The only slithly bad part about is that few used values have a name starting with "last_*".
      Maybe we can look to rename they to have more matching to active and past time.
This done to have prepared for future API changes where add-on can return a init status to Kodi and
inform add-on is usable or not.

To make this then working for the new API must only the call from construction removed and the commented override uncommented.
@AlwinEsch AlwinEsch force-pushed the Piers-Dev branch 2 times, most recently from 60b4620 to 261dfae Compare May 31, 2026 16:00
@AlwinEsch AlwinEsch changed the title Temporary for Jenkins tests - Update to projectM v4.x Update to projectM v4.x (another try) Jun 14, 2026
@AlwinEsch

AlwinEsch commented Jun 25, 2026

Copy link
Copy Markdown
Member Author

NOTE: has fixed a crash on NVIDIA Shield TV, for some reason has it on init crashed there, but all other OS and all other Android systems was OK.

The crash was produced by this line:
https://github.com/AlwinEsch/visualization.projectm/blob/Piers-Dev/src/Main.cpp#L220
Where calls PROJECTM_PLAYLIST_EXPORT uint32_t projectm_playlist_play_next(projectm_playlist_handle instance, bool hard_cut); the hard_cut was set as false before, by set as true has it worked.

The strange was that the crash was not directly come by this code line and call. Crash was coming later on call from Kodi of GetPresets(...) and after his return Kodi crashed byself (not mater if return values or not. Maybe at one bad place in projectM has done a memory or stack overwrite on memory outside of him and where then brought the crash in Kodi.

But I'm having a lot of guesswork because it was only there with NVIDIA (probably because of Android 11 🤔?) and with all the others it was OK.

@garbear

garbear commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

I've attempted to test this everywhere I can:

  • macOS ARM - Works perfectly
  • Win32/64/ARM (Jenkins) - Can't build on Jenkins, preset paths too long
  • Win64 (local) - Doesn't work, playing a song has a black vis in the background, switching to fullscreen vis crashes Kodi (
  • Shield TV - Can't install new Kodi, my library is taking up almost all of the 16GB of storage
Screenshot 2026-06-25 at 7 00 02 PM

@garbear

garbear commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

OK, I was able to verify success on Android using the zip from the build artifacts: https://jenkins.kodi.tv/blue/organizations/jenkins/xbmc%2Fvisualization.projectm/detail/PR-137/34/artifacts/

Shield TV working great.

Implemented in ProjectM on Dec 7, 2025 with c6e02c9
Not included in the 4.1.6 release
Before was it hardcoded to Stereo and where the AI was not happy.
This includes now the support for diverent channels amount
On versions lower as 10.15 for OSX and 13.0 for embedded is std::filesystem not complete supported and compile fails there.
Unfortunately, due to numerous problems, it currently no longer makes sense to use this add-on under Windows.
On the one hand, Angle rendering using DirectX causes too many problems and incorrect representations.
On the other hand, projectM version 4 for GLES requires minimum version 3.2, which is not available under Windows using DirectX.
In addition, Kodi crashes when changing full screen when this add-on is in use.

Support for Windows could possibly be brought back in the future.
@AlwinEsch

Copy link
Copy Markdown
Member Author

Pull request code has been updated again, as a new change the Windows support for the add-on will unfortunately be removed, see description in the associated commit.

@AlwinEsch

Copy link
Copy Markdown
Member Author

It comes in now. Is not nice but Windows support then removed 😢.
Maybe if Kodi becomes a Vulkan GPU support it can come back to WIndows.

@AlwinEsch AlwinEsch merged commit 56becb9 into xbmc:Piers Jul 1, 2026
3 checks passed
@AlwinEsch AlwinEsch deleted the Piers-Dev branch July 1, 2026 18:01
@garbear

garbear commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Nice work!

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.

3 participants