No description
Find a file
Froz 9134dad61f
Some checks failed
Build Check / Stream Deck plugin (push) Has been cancelled
Build Check / macOS, arm64 (push) Has been cancelled
add text
2026-10-02 01:07:40 +02:00
.github stream deck plugin 2026-10-01 22:43:53 +02:00
Claude outputs ïnit: fork 2026-10-01 22:13:34 +02:00
cmake ïnit: fork 2026-10-01 22:13:34 +02:00
src add text 2026-10-02 01:07:40 +02:00
streamdeck add text 2026-10-02 01:07:40 +02:00
test ïnit: fork 2026-10-01 22:13:34 +02:00
vendor/imgui ïnit: fork 2026-10-01 22:13:34 +02:00
.clang-format ïnit: fork 2026-10-01 22:13:34 +02:00
.gitignore ïnit: fork 2026-10-01 22:13:34 +02:00
.gitmodules ïnit: fork 2026-10-01 22:13:34 +02:00
CMakeLists.txt ïnit: fork 2026-10-01 22:13:34 +02:00
dependencies_check.cmake ïnit: fork 2026-10-01 22:13:34 +02:00
ImGui.cmake ïnit: fork 2026-10-01 22:13:34 +02:00
install.cmake ïnit: fork 2026-10-01 22:13:34 +02:00
LICENSE.md ïnit: fork 2026-10-01 22:13:34 +02:00
packaging-macos.cmake ïnit: fork 2026-10-01 22:13:34 +02:00
README.md add text 2026-10-02 01:07:40 +02:00
setup.sh stream deck plugin 2026-10-01 22:43:53 +02:00

projectM SDL Frontend — Control Window Edition

A fork of the projectM SDL frontend for macOS on Apple Silicon (arm64) only.

It listens to audio (including the system audio output on macOS 14.4+) and renders Milkdrop-style visuals with libprojectM. Compared to upstream, this fork:

  • Moves every control into a separate control window. The visualizer window only ever shows the visuals, so it can go fullscreen on a projector or second display while you operate everything from the control window.
  • Lets you configure everything from the UI. Playback, transitions, hard cuts, preset and texture folders, rendering, visualizer display/fullscreen/vsync, audio device, UI scale and theme. Changes apply immediately and are saved automatically — there is no "Save" button.
  • Adds named playlists. Create, rename, duplicate and delete playlists; add presets or whole folders; reorder by drag & drop; copy presets between playlists; filter by name. Playlists are stored as .m3u files.
  • Makes autoplay a simple toggle. With autoplay on, presets switch after the display duration (in order or shuffled). With autoplay off, the current preset stays until you change it.
  • Disables all keyboard shortcuts and mouse actions on the visualizer. Nothing happens by accident when a key is pressed or the mouse is clicked or scrolled over the visuals.

Using the application

When projectM starts, two windows open: the visualizer and the control window.

  • Transport bar (top of the control window): current preset and playlist, Previous / Next / Random, Autoplay and Shuffle toggles, a countdown to the next preset, and buttons to show/hide the visualizer and to toggle fullscreen.
  • Playlists tab: playlists on the left, presets of the selected playlist on the right.
    • Double-click a preset to play it. This makes its playlist the active one.
    • Cmd-click / Shift-click to select several presets. Drag them to reorder, or onto a playlist on the left to copy them there. Right-click for more actions (play next, move to top/bottom, copy to playlist, show in Finder...).
    • More... offers sorting, shuffling the order, removing duplicates or missing files, and clearing the playlist.
    • On first start, an All Presets playlist is created from the configured preset folder(s). It can be rebuilt at any time from More... or the Visuals tab.
  • Playback, Visuals, Display, Audio, Interface tabs: all settings. Hover over a setting's name for a description. Reset restores the default value.

Drag & drop:

  • Files or folders dropped onto the control window are added to the playlist shown in the Playlists tab.
  • Presets dropped onto the visualizer are queued after the current preset (and played right away, if enabled). A folder dropped onto the visualizer creates a new playlist named after the folder (configurable).

Windows:

  • Closing the visualizer window only hides it; show it again from the control window.
  • Closing the control window (or using Quit from the macOS application menu) quits projectM.
  • By default, fullscreen uses a desktop-sized window instead of a separate macOS Space, so the control window can stay visible on the same display. Enable Always on Top for the control window in the Interface tab to keep it above a fullscreen visualizer. Native macOS Spaces fullscreen can be enabled in the Display tab.

Files:

  • Settings: ~/Library/Preferences/projectM/projectMSDL.properties
  • Playlists: ~/Library/Preferences/projectM/Playlists/*.m3u (one preset path per line; can be edited by hand while projectM is not running)
  • Log file: ~/Library/Preferences/projectM/projectMSDL.log

Quick start: one script does everything

git clone --recurse-submodules <this repository> frontend-sdl-cpp
cd frontend-sdl-cpp
./setup.sh

setup.sh checks your Mac, installs the Xcode command line tools and Homebrew packages if needed, builds libprojectM (v4.1.7, as a static library), downloads the Cream of the Crop preset pack (~9,800 presets) and the Milkdrop texture pack, builds the app with both bundled inside, signs it for your Mac and installs it to /Applications/projectM.app.

Everything it downloads and builds is kept in the .build folder, so running it again is quick. Run it again at any time to update the presets and rebuild. Useful options (see ./setup.sh --help for all of them):

  • --classic-presets also bundles the original Milkdrop presets.
  • --preset-dir DIR / --texture-dir DIR bundle your own presets or textures (can be repeated).
  • --dest ~/Applications installs somewhere else; --no-install only builds (the app ends up in .build/install).
  • --clean rebuilds everything from scratch.
  • --no-streamdeck skips the Stream Deck plugin (it's only built when the Stream Deck app is installed).

If you already used projectM before, rebuild the "All Presets" playlist once to pick up newly bundled presets (Playlists tab > More... > Rebuild from Preset Folders).

Text on the visuals

The Text tab of the control window (or the Text: On/Off button next to Blackout) shows your own text in the center of the visuals, reacting to the music:

  • 13 styles: Pulse, Neon, Glitch (RGB split, sliced lines, scrambled letters), Wave, Bounce, Shake, Rainbow, Strobe, Breathe, Outline, Cyberpunk (cyan/magenta ghosts, scanlines, glitches), Hologram (flicker, rolling scanlines) and Static.
  • 25 bundled fonts (Tech, Retro, Neon, Display and Handwritten looks, all open-source licensed) or any .ttf / .otf / .ttc file.
  • Size in percent of the screen height (long text is shrunk to fit), color or inverse of the visuals, audio reactivity, opacity and fade time. Multi-line text works too.
  • The text stays visible during a blackout, e.g. for a "Back in 5 minutes" message.

All of it is also available from projectmctl and the Stream Deck:

projectmctl text show style=neon font=tilt-neon color=#ff2a6d size=25 "Back in 5"
projectmctl text toggle style=cyberpunk font=orbitron color=invert "NIGHT CITY"
projectmctl text set size=30         # change options without showing / hiding
projectmctl text hide
projectmctl text styles              # list the styles (text fonts: list the fonts)

Remote control: projectmctl

projectmctl controls a running projectM from the command line, e.g. from scripts, hotkey tools (Raycast, Alfred, BetterTouchTool, Shortcuts...) or over SSH. setup.sh installs it next to the app and puts it on your PATH.

projectmctl next                 # next preset (alias: forward)
projectmctl prev                 # previous preset (alias: back)
projectmctl autoplay off         # on | off | toggle
projectmctl playlist next        # cycle through your own playlists (prev also works)
projectmctl blackout             # fade to black (optionally: blackout 5 for a 5 second fade)
projectmctl resume               # fade back in (optionally: resume 0 to cut back in instantly)
projectmctl status               # current preset, playlist, autoplay and blackout state
projectmctl help                 # all commands
  • playlist next / playlist prev only cycle through playlists you created: "All Presets" and empty playlists are skipped. The order is the same as in the control window. playlist list and playlist play <name> are also available.
  • While the visuals are completely black, projectM doesn't render at all (saving power), so autoplay doesn't switch presets during a blackout. The control window has a matching Blackout / Resume button, and the default fade duration is set in the Playback tab.
  • Exit codes: 0 success, 1 the command failed (message on stderr), 2 projectM is not running.
  • It talks to projectM through a Unix socket that only your user can access: ~/Library/Application Support/projectM/control.sock (override with the PROJECTM_SOCKET environment variable). The protocol is one text line per connection, so you can also use it without projectmctl: echo "playlist next" | nc -U ~/Library/Application\ Support/projectM/control.sock.

Stream Deck plugin

The streamdeck folder contains a plugin for the Elgato Stream Deck app (version 7.1 or newer). setup.sh builds it and installs it automatically when the Stream Deck app is installed; the actions then appear in the projectM category. It talks to projectM through the same socket as projectmctl, so every projectmctl feature is available, and the keys show the live state:

Action Key Stream Deck + dial
Next / Previous / Random Preset switch preset –
Preset Dial – turn: previous / next preset; press: random (configurable); strip shows preset and time to next
Autoplay, Shuffle toggle, or set to on / off; green while on turn right: on, left: off; press: toggle
Next / Previous Playlist cycle your playlists; shows the active one –
Playlist Dial – turn: cycle playlists; press: toggle blackout (configurable)
Play Playlist play the playlist chosen in the key's settings (drop-down filled from projectM); highlighted while playing –
Blackout toggle, fade out or fade in, with optional fade duration; red while black turn left: fade out, right: fade in; press: toggle
Now Playing playlist, position, preset name and a bar showing the time to the next preset –
Text show / hide your text with the key's style, font, size, color (or inverse) and reactivity, all set in the key's settings; previews the text and shows ON AIR while it's on screen; changes apply live turn: text size; press / tap: show / hide

Every key shows "OFFLINE" while projectM isn't running, and a warning triangle if a command fails (e.g. the chosen playlist doesn't exist).

To build it by hand: cd streamdeck && npm ci && npm run build && npm run pack, then double-click dist/com.froz.projectm.streamDeckPlugin. During development, npx streamdeck link com.froz.projectm.sdPlugin and npm run watch reload the plugin on every change. npm run icons regenerates the default images.

Building from source manually

Requirements: a Mac with Apple Silicon, macOS 12 or newer (system audio capture needs macOS 14.4+), the Xcode command line tools and Homebrew.

xcode-select --install
brew install cmake ninja sdl2 poco freetype git

1. Build and install libprojectM

git clone --recurse-submodules https://github.com/projectM-visualizer/projectm.git
cmake -G Ninja -S projectm -B projectm/cmake-build \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_OSX_ARCHITECTURES=arm64 \
  -DCMAKE_INSTALL_PREFIX=~/dev/projectm-install \
  -DBUILD_SHARED_LIBS=ON
cmake --build projectm/cmake-build --parallel
cmake --install projectm/cmake-build

This fork only uses libprojectM's core library, not its playlist library.

2. Build this frontend

From this repository's directory (remember to initialize the Dear ImGui submodule):

git submodule update --init
cmake -G Ninja -S . -B cmake-build \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_PREFIX_PATH="$HOME/dev/projectm-install;$(brew --prefix)" \
  -DCMAKE_INSTALL_PREFIX=~/dev/projectm-app
cmake --build cmake-build --parallel
cmake --install cmake-build

projectM.app will be in ~/dev/projectm-app/, with projectmctl in projectM.app/Contents/MacOS/. To bundle presets and textures into the app, add -DPRESET_DIRS=/path/to/presets -DTEXTURE_DIRS=/path/to/textures to the first cmake command. Otherwise, set your preset and texture folders in the control window's Visuals tab and rebuild the "All Presets" playlist.

Curated presets: presets-cream-of-the-crop. Textures used by many presets: presets-milkdrop-texture-pack.

You can also run the binary straight from the build directory:

cmake-build/src/projectM.app/Contents/MacOS/projectM --presetPath /path/to/presets --texturePath /path/to/textures

Run it with --help to see all command-line options. Settings passed on the command line are marked with [!] in the control window.

Platform support

The build refuses to configure on anything but macOS/arm64. -DPROJECTMSDL_ALLOW_UNSUPPORTED_PLATFORM=ON skips this check for development compile checks only; such builds use a Dear ImGui file browser instead of the native macOS file dialogs and are not supported.

License

GNU General Public License v3.0, like the upstream projectM SDL frontend. See LICENSE.md.