Hi, I've been running a fork (d1ggs/lumux) with a few changes I think belong upstream. Before opening PRs I wanted to check what you'd actually want. Everything below is tested on my setup (GNOME on Debian 13, bridge + gradient lightstrip) and has unit tests.
Full disclosure before anything else: I developed this with heavy use of AI tooling (Claude Code). I directed the work, reviewed the changes, and verified everything live on my hardware, but most of the code was AI-written. If this project doesn't accept AI-assisted contributions, that's completely fine, feel free to close this issue. In that case treat the notes below as bug reports, since the underlying issues exist regardless of how I fixed them.
1. Stop the monitor picker from appearing on every launch
Lumux requests the ScreenCast portal session without persistence, so the "share which monitor?" dialog shows up on every start. This is especially annoying with autostart. The portal already supports remembering the grant: pass persist_mode: 2 in SelectSources, store the restore_token that Start returns, and send it back next time. Two details I ran into while implementing it:
- If the stored token is malformed,
SelectSources raises InvalidArgument instead of falling back to the picker (the spec only promises graceful fallback for well-formed tokens that can't be restored), so there is a retry path that clears the token.
- Persisting the token exposed a race in
SettingsManager.save(), which is now atomic (tempfile + os.replace) and holds a lock.
2. Lights off on suspend, sync resumes on wake
Subscribes to logind's PrepareForSleep with a delay inhibitor, turns the lights off when the machine sleeps, and restarts video sync after wake. Getting the lights off reliably was harder than expected: NetworkManager reacts to the same signal and takes the network down within about 150ms, so REST calls from the sleep handler never arrive. What works is streaming black frames over the already-open DTLS socket immediately (within the first ~40ms), since the bridge keeps a lamp at its last streamed color once the session times out during sleep. The REST teardown still runs afterwards as best effort. I went through six suspend/test cycles before landing on this; the dead ends are in the commit history if you want the details.
Two things to consider: it needs --system-talk-name=org.freedesktop.login1 in the manifest (Flathub manifest too), and I could only test on GNOME/systemd/NetworkManager with a single entertainment area. Could go behind a setting if you'd rather.
3. Independent bugfixes
- A pending reading-mode auto-activation timer can survive
turn_off() and re-light the lamps about a second later. The current_mode != OFF guard in _finish_switch_to_reading doesn't catch this case because turn_off() leaves the mode as OFF.
bridge_client swallows all failures (except BridgeError: return False), which made the suspend work very hard to debug. Added logging and optional per-call timeouts.
channel.members[].service.rid in the entertainment config are entertainment service ids, not light ids. Added a resolve_light_ids() helper that pairs them through each device's services list, same technique as _refresh_spatial_data.
- The sync button label goes stale when the mode changes through anything other than a button click. Now driven by the mode-changed callback.
Let me know which of these you'd take and in what shape, and I'll open the PRs.
Hi, I've been running a fork (d1ggs/lumux) with a few changes I think belong upstream. Before opening PRs I wanted to check what you'd actually want. Everything below is tested on my setup (GNOME on Debian 13, bridge + gradient lightstrip) and has unit tests.
Full disclosure before anything else: I developed this with heavy use of AI tooling (Claude Code). I directed the work, reviewed the changes, and verified everything live on my hardware, but most of the code was AI-written. If this project doesn't accept AI-assisted contributions, that's completely fine, feel free to close this issue. In that case treat the notes below as bug reports, since the underlying issues exist regardless of how I fixed them.
1. Stop the monitor picker from appearing on every launch
Lumux requests the ScreenCast portal session without persistence, so the "share which monitor?" dialog shows up on every start. This is especially annoying with autostart. The portal already supports remembering the grant: pass
persist_mode: 2inSelectSources, store therestore_tokenthatStartreturns, and send it back next time. Two details I ran into while implementing it:SelectSourcesraisesInvalidArgumentinstead of falling back to the picker (the spec only promises graceful fallback for well-formed tokens that can't be restored), so there is a retry path that clears the token.SettingsManager.save(), which is now atomic (tempfile +os.replace) and holds a lock.2. Lights off on suspend, sync resumes on wake
Subscribes to logind's
PrepareForSleepwith a delay inhibitor, turns the lights off when the machine sleeps, and restarts video sync after wake. Getting the lights off reliably was harder than expected: NetworkManager reacts to the same signal and takes the network down within about 150ms, so REST calls from the sleep handler never arrive. What works is streaming black frames over the already-open DTLS socket immediately (within the first ~40ms), since the bridge keeps a lamp at its last streamed color once the session times out during sleep. The REST teardown still runs afterwards as best effort. I went through six suspend/test cycles before landing on this; the dead ends are in the commit history if you want the details.Two things to consider: it needs
--system-talk-name=org.freedesktop.login1in the manifest (Flathub manifest too), and I could only test on GNOME/systemd/NetworkManager with a single entertainment area. Could go behind a setting if you'd rather.3. Independent bugfixes
turn_off()and re-light the lamps about a second later. Thecurrent_mode != OFFguard in_finish_switch_to_readingdoesn't catch this case becauseturn_off()leaves the mode asOFF.bridge_clientswallows all failures (except BridgeError: return False), which made the suspend work very hard to debug. Added logging and optional per-call timeouts.channel.members[].service.ridin the entertainment config are entertainment service ids, not light ids. Added aresolve_light_ids()helper that pairs them through each device'sserviceslist, same technique as_refresh_spatial_data.Let me know which of these you'd take and in what shape, and I'll open the PRs.