cpuguy83
cpuguy83.bsky.social
cpuguy83
@cpuguy83.bsky.social
I used to use nano because I could not exit vim.
Then I learned vim and, when EDITOR is not set, I get dropped into nano and cannot exit.
November 19, 2025 at 12:10 AM
If you got this far, maybe make sure you actually enjoy the rest of your day 😀
November 15, 2025 at 7:33 PM
As mentioned before I don't send a response back to the script since the script can't meaningfully do anything with a response (w/o being racey).

Instead I have the daemon call swayosd-client to make a pretty brightess level graphic on the monitor.
I like it... I may make that configurable.
November 15, 2025 at 7:33 PM
The shell script I register with my hyprland config is bound to brightness up/down events.

When it starts up it uses hyprctl to get the currently active monitor and assume this is the display whose brightness is to be adjusted.
I take the monitor value from there and directly feed it into the API.
November 15, 2025 at 7:33 PM
So now I've got this daemon that I can either interact with over stdin (for easy debugging), or it can be socket activated (how I actually use it).

Requests come in and modify a desired state.
Single worker takes the desired state and makes it reality.
November 15, 2025 at 7:33 PM
Reading the brightness from the device was fairly straight forward.
Writing, was trickier. I ended up doing some back and forth with codex and eventually *it* noticed the framing for the request was off and updated it and it all worked.
Wonderful!
November 15, 2025 at 7:33 PM
I didn't really want to depend on ddcutil as there is some overhead there but I already have the device open since we had that detection logic on daemon startup.
November 15, 2025 at 7:33 PM
The API right now is just line-based:

<display id> <op> [<value>]\n

It doesn't currently send a response back, b/c the script can't handle errors (nothing to do), and reacting to the new brightness level needs to happen in a synchronized, not parallelized like the script is expected to run as.
November 15, 2025 at 7:33 PM
On startup the daemon goes through /sys/class/drm to find ddc capable devices attached to a display.

B/c of the 2 cable setup, I need to keep a mapping of devices that are the same display but different i2c buses.
I did this by reading the serial number of the edid and matching them up.
November 15, 2025 at 7:33 PM
So I ended up writing a daemon that that the script makes an API call to.
The API accepts 4 ops:

GET, SET, ADD, SUB (get/set for debug)

The API request updates the desired state based on the op.
And GET really becomes ADD(0).
Once accepted the writer is woken up to sync actual w/ desired state.
November 15, 2025 at 7:33 PM
Another problem with the script is the scripts end up running in parallel with multiple key presses and makes for racey behavior.
I considered setting up flock to deal with this, but the script was just so slow I went another route.
November 15, 2025 at 7:33 PM
Each invocation of the script needs to either detect the displays and figure out that mapping or just statically map things though config.

The detection is really slow, especially for something that's supposed to react to rapid key presses.
Static config would work, but is annoying (to me).
November 15, 2025 at 7:33 PM
Since each invocation needs to:

1. Determine the active display
2. Convert active display to the correct secondary HDMI connection
3. Read the current brightness value
4. Write the updated value back

Technically, ddcutil supports doing 3+4 in a single execution, but its still multiple DDC calls.
November 15, 2025 at 7:33 PM
I started playing with ddcutil to make these adjustments, this works... it is fairly slow, though.
Especially slow in my script that reacts to the keyboard combo.
November 15, 2025 at 7:33 PM
First I had to add an additional connection to my monitors so they can go over HDMI.
Right now I have 1 going DP -> HDMI and one going HDMI -> HDMI (both in addition to the DP->DP I already had).

I'll probably just get another DP->HDMI cable and just use 1 cable each.
For now I need to deal with 2.
November 15, 2025 at 7:33 PM
Reposted by cpuguy83
This may need to be a blog post, but users tend to think ingress-nginx is simple because they can go to town with annotations. In reality, the features that they want are actually really complex to expose safely. This is why the project struggled with CVEs.

“Simple for whom” is the question
November 13, 2025 at 9:52 PM
Misspelled my name 🤣
November 11, 2025 at 7:50 PM