Skip to content

Audio reactive live background#2449

Draft
weissi1994 wants to merge 2 commits intonoctalia-dev:mainfrom
weissi1994:livepaper
Draft

Audio reactive live background#2449
weissi1994 wants to merge 2 commits intonoctalia-dev:mainfrom
weissi1994:livepaper

Conversation

@weissi1994
Copy link
Copy Markdown

@weissi1994 weissi1994 commented Apr 12, 2026

Motivation

It adds a audio reactive live desktop & lockscreen wallpaper backed by projectM which monitors the active pulseaudio output (with microphone fallback).

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring

Related Issue

  • None

Testing

Describe how you tested your changes and mark the relevant items.

  • Tested on niri
  • Tested on Hyprland
  • [~] Tested on sway (tested on scroll a fork of sway)
  • Tested with different bar positions and density settings
  • Tested at different interface scaling values
  • Tested with multiple monitors (if applicable)

Screenshots / Videos

output_720p.mp4

Checklist

  • Code follows project style guidelines
  • Self-reviewed my code
  • No new warnings or errors
  • Documentation or comments updated (if relevant)

Additional Notes

This Draft PR is primarily to act as POC implementation (generated with the help of ai) to check if the community is interested in this feature in general.
Most if it likely needs to be rewritten and/or redesigned entirely, would appreciate some guidance here.

dweissengruber added 2 commits April 12, 2026 16:28
upd

fix

fix

upd

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=2bbec2cf09cb1c92c6ef87bbe39e25f35f8a1a42' (2026-04-10)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=79e6d7a3ee47f0f6bca306e9eb215fdc48627114' (2026-04-10)

upd

upd

upd

upd

upd

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=79e6d7a3ee47f0f6bca306e9eb215fdc48627114' (2026-04-10)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=e3b4a41dd7f484fc7c95afbdd392a3921a5a80e8' (2026-04-10)

upd

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=e3b4a41dd7f484fc7c95afbdd392a3921a5a80e8' (2026-04-10)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=f42d7e2d608531244a6e7b207ec09b93cd01baf6' (2026-04-10)

upd

upd

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=f42d7e2d608531244a6e7b207ec09b93cd01baf6' (2026-04-10)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=2ab9b5fe39054d8b3023e0254a875b20cb058595' (2026-04-10)

upd

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=2ab9b5fe39054d8b3023e0254a875b20cb058595' (2026-04-10)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=62985279520854050aaafe06055e38fb2f122a0e' (2026-04-10)

upd

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=62985279520854050aaafe06055e38fb2f122a0e' (2026-04-10)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=840a70049dc3af1cbed88181b27df779ed2140bb' (2026-04-10)

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=840a70049dc3af1cbed88181b27df779ed2140bb' (2026-04-10)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=70e34b8504de5d2b5bec96a9908d8bd82ca2097e' (2026-04-10)

upd

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=70e34b8504de5d2b5bec96a9908d8bd82ca2097e' (2026-04-10)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=a3f89e57d7f3962a33a0bccc4edc6c51c9387d0c' (2026-04-10)

jpeg approach

upd

upd

upd

upd

upd

upd

upd

uod

upd

upd

upd

upd

upd

upd

upd

upd

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=a3f89e57d7f3962a33a0bccc4edc6c51c9387d0c' (2026-04-10)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=53e618139db46d54365b69edf8af5533b5dbd3e8' (2026-04-11)

upd

upd

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=53e618139db46d54365b69edf8af5533b5dbd3e8' (2026-04-11)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=84caecdbca71ae9b6f32cfa313788b61f43d8757' (2026-04-11)

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=84caecdbca71ae9b6f32cfa313788b61f43d8757' (2026-04-11)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=86211df4e01ca86e9d121b92ff294477f22642fd' (2026-04-11)

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=86211df4e01ca86e9d121b92ff294477f22642fd' (2026-04-11)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=a9d7a1061a36c5cbb1bbcbec41c2a4289275b769' (2026-04-11)

upd

upd

upd

flake.lock: Update

Flake lock file updates:

• Updated input 'projectM-waylivepaper':
    'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=a9d7a1061a36c5cbb1bbcbec41c2a4289275b769' (2026-04-11)
  → 'git+ssh://git@git.n0de.biz/daniel/projectM-waylivepaper?ref=main&rev=c99d0faa586f06744491d54d262f1b18b9b5a0cb' (2026-04-11)

upd

upd

upd

upd

upd

upd

upd

upd

upd

upd

upd

fix: use smooth_transition=false for all preset loads

projectm_load_preset_file with smooth_transition=true on a freshly
created instance starts a soft blend from the nonexistent previous
preset. That blend stays stuck on the empty side and renders at the
default ~512x512 size until a second preset load displaces it — the
exact cause of the black bars at top/right until next-track.

Hard load (false) activates the preset immediately at the correct
window size, matching the reference waylivepaper implementation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

fix: remove warm-up, load preset before first render_frame (reference pattern)

The warm-up render was backwards: we were calling render_frame() BEFORE
load_preset_file(), then loading the preset. The reference implementation
(waylivepaper) does the opposite:

  set_window_size(W, H)
  load_preset_file(preset, false)   ← before any render_frame
  render_frame()                    ← first render, correct size

A hard load (smooth=false) causes projectM to initialise the preset at
the stored window size immediately, without needing a prior throw-away
frame. Calling render_frame() first was causing projectM to run its
default visualisation at the internal 512×512 default size.

Additional fixes:
- Track m_loadedPreset; on FBO resize (createFramebufferObject called
  with new size), force-reload the current preset at the new dimensions.
- Hold back rendering (fill black) until the first preset is loaded, so
  the 512×512 default visualisation is never shown to the user.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

debug: log FBO/init sizes; use actual FBO dims for initProjectM

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

fix: render projectM at logical pixels, blit up to Qt device-pixel FBO

The Qt QQuickFramebufferObject is created at device pixels (logical × dpr),
but FBO 0 (the EGL window surface) under Wayland fractional scaling is at
logical pixels. We were rendering projectM at the device-pixel viewport
(3840×2560 in the logs), but FBO 0 only holds 2880×1920 — OpenGL clips the
render to the lower-left logical area, causing the "visualization in the
lower-left with black bars at top/right" symptom.

Fix:
- Sync devicePixelRatio from the QQuickWindow in synchronize().
- Compute logical size: pm_w/h = round(fbo_w/h / dpr).
- Init projectM, set window size, and set glViewport at logical size.
- Blit from FBO 0 (pm_w×pm_h) → Qt FBO (w×h) with GL_LINEAR upscale.
- createFramebufferObject: track m_pmSize at logical size; reload preset
  only when the logical size actually changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

fix: add QQuickWindow include for devicePixelRatio

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

upd

upd

upd

upd

upd

upd

upd

review

review

upd

upd

upd
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