New CI job matrix (build-framework):
- Tests framework builds on both arm64 and x86_64
- Tests with and without C++ interface
- Runs strict validation after build AND after install
- Verifies installed frameworks match build output
Test script improvements:
- Exhaustive header lists (all C API + all C++ headers)
- Exact header count validation (catches stale/unexpected files)
- Strict mode (STRICT=1) where SKIPs become FAILs
- Info.plist CFBundleExecutable validation
- Symlink target verification (Current, Headers, Resources)
- Mach-O dylib binary type check
- dylib install name validation
- Flexible framework search across build tree and install prefix
- Test pass counter in summary
- Add missing Renderer/TextureTypes.hpp to C++ framework headers
- Skip pkg-config generation for playlist in framework mode
- Use stored framework path property for install instead of TARGET_FILE_DIR
- Show compiler errors on linkability test failure instead of suppressing
- Fix comment about framework output location
The previous implementation using CMake's built-in FRAMEWORK property
had two issues:
1. Headers were not copied into the framework at all
2. PUBLIC_HEADER flattens directory structure, breaking C++ interface
This replaces the CMake FRAMEWORK support with a custom MacOSFramework
cmake module that:
- Builds proper framework bundles from scratch
- Preserves header directory hierarchy (Audio/, Renderer/ subdirs)
- Creates correct symlink structure (Versions/A, Current, etc.)
- Generates Info.plist with bundle metadata
Also adds CI test script (scripts/test-macos-framework.sh) that validates:
- Framework directory structure
- Header completeness
- Linkability (compile and link test program)
Fixes the empty framework issue reported after ef00cfc8e.
Adds projectm_set_preset_start_clean() and projectm_get_preset_start_clean()
functions to control whether new presets start with a black canvas or inherit
the previous preset's last frame.
Default behavior remains unchanged (copy previous frame), but applications
can now opt-in to clean starts by setting this flag to true.
Fixes#298
Adds projectm_playlist_set_preset_load_event_callback() to allow applications
to handle preset loading themselves. This enables loading presets from:
- Archives (ZIP files)
- Network sources (HTTP)
- Custom storage solutions
- Asynchronous loading patterns
When the callback is set and returns true, the playlist library skips its
default filesystem-based loading. If the callback returns false or isn't set,
the default behavior is used.
Fixes#946
Adds a callback that allows applications to provide textures from
non-filesystem sources like archives, network, or procedurally
generated content. The callback receives the texture name and can
return either raw pixel data or an existing OpenGL texture ID.
Changes:
- Add SetTextureLoadCallback API for custom texture loading
- Add texture ownership tracking to prevent deletion of app-provided textures
- Update texture creation to use stb_image instead of SOIL
- Add validation and error logging for callback-provided textures
Fixes#870
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds ENABLE_MACOS_FRAMEWORK cmake option to build projectM-4.framework
and projectM-4-playlist.framework bundles instead of plain dylibs.
Only available on macOS with shared library builds.
The frameworks include all public headers in the Headers/ directory
and use standard macOS framework versioning (Version A).
Fixes#924
Covers the fix for issue #940 with tests for:
- Parenthesized constructor with binary operators
- Double-nested parentheses
- Both operands parenthesized
- Chained operators after parens
The parser rejected valid HLSL like `float2 var = (float2(x,y)) * scalar`
with "expected ';'" errors. When parsing a parenthesized expression, the
loop would break before consuming the closing paren, so subsequent binary
operators were never seen.
Moves end-char consumption into the else block and checks for operators
after consuming the paren, continuing the loop if one is found.
Fixes#940
vcpkg will emit additional logging output if no NuGet.exe is installed, which will then make the pwsh command replacement fail as not just the executable location is echoed.
for some unknown reason I used "-l:<lib>" in the .pc files while it should just be "-l<lib>". This would prevent libprojectM (and the playlist lib) from being linked in projects using pkgconfig.
Previously, if the TextureManager was recreated, e.g. when changing the texture paths, all loaded textures were deleted, even if currently in use by a preset. Storing textures and samplers as shared pointers instead of weak pointers will make sure the objects are kept alive until the preset is unloaded.
Signed-off-by: Kai Blaschke <kai.blaschke@kb-dev.net>
Since this might be vendor-specific behavior, a new API function to configure the X/Y texel offsets has been added.
Signed-off-by: Kai Blaschke <kai.blaschke@kb-dev.net>
All waves were rendered upside-down, breaking presets requiring the wave to be at the top or bottom due to warp movement. Using the flipped transformation matrix for drawing will take care of this globally.
Also fixed two small mistakes regarding operators.
Signed-off-by: Kai Blaschke <kai.blaschke@kb-dev.net>
Only custom waves set the point size to 2, default waveforms still render the 2x2 pattern when using dots. Other draw calls aren't affected as they only draw lines/triangles, but it's good practice to not leave the uniform in an undefined state.
Signed-off-by: Kai Blaschke <kai.blaschke@kb-dev.net>