Skip to main content

Driver and Niri integration for the Ulanzi Stream Controller D200X

Project description

ulanzi-studio-niri

A Linux daemon that drives the Ulanzi Stream Controller D200X and integrates it with the Niri Wayland compositor.

Buttons can:

  • Trigger Niri actions (niri msg action ...)
  • Launch arbitrary commands
  • Control media (playerctl / wpctl)
  • Take screenshots (grim / slurp)
  • Send keystrokes (wtype / ydotool)
  • Switch between configured pages
  • Adjust deck brightness

The wide bottom-right LCD displays a clock, system stats, or live encoder information.

Hardware

  • 13 LCD buttons at 196×196
  • 1 wide LCD button at 458×196 (bottom-right; driven by the small-window subsystem)
  • 2 plain physical buttons
  • 3 rotary encoders (each with click)

Installation

This project uses uv and runs against the system Python interpreter.

# Development install
uv venv --python /usr/bin/python3 .venv
uv sync

# End-user install (creates ~/.local/bin/ulanzi-niri)
uv tool install .

udev rule (required)

Out of the box the deck's hidraw nodes are owned by root. Install the udev rule so the daemon can talk to it as your user:

ulanzi-niri install-udev
# follow the printed `sudo` commands; replug the deck afterwards

Run as a service

mkdir -p ~/.config/systemd/user
cp packaging/ulanzi-niri.service ~/.config/systemd/user/
systemctl --user enable --now ulanzi-niri

Configuration

Configuration lives at ~/.config/ulanzi-niri/config.toml. See examples/config.toml.

Icons

Icon names in [[page.button]] are resolved in this order, first match wins:

  1. ~/.config/ulanzi-niri/icons/<name> — your own overrides
  2. <install>/assets/icons/<name> — bundled icons (if any)
  3. ~/.local/share/icons/, /usr/share/icons/, /usr/share/pixmaps/ — freedesktop icon directories, searched recursively

A name with an extension (firefox.png) matches that filename anywhere under the search roots. A bare name (firefox) matches firefox.png or firefox.xpm, preferring the largest available pixel size (parsed from NxN directory components). SVG icons are not currently supported — drop a PNG into ~/.config/ulanzi-niri/icons/ for SVG-only themes.

Development

uv run ulanzi-niri doctor       # diagnose environment
uv run ulanzi-niri push         # one-shot push of current config
uv run ulanzi-niri sniff        # observe HID traffic
uv run pytest                   # tests
uv run ruff check .             # lint

Status

All physical inputs are wired: the 13 LCD buttons, the wide tile (pos 13), the two plain hardware buttons (pos 14, 15), and all three rotary encoders (press + rotate). Streaming for the 4th-row buttons and encoders requires a one-time ENABLE_INPUT_STREAMING (cmd 0x0002) packet on connect, which the daemon sends automatically; without it the firmware silently consumes encoder rotates (routing them to its built-in brightness handler). Opcode discovered empirically by sweep.

Credits

Protocol details adapted from redphx/strmdck.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ulanzi_studio_niri-1.0.0.tar.gz (84.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ulanzi_studio_niri-1.0.0-py3-none-any.whl (34.6 kB view details)

Uploaded Python 3

File details

Details for the file ulanzi_studio_niri-1.0.0.tar.gz.

File metadata

  • Download URL: ulanzi_studio_niri-1.0.0.tar.gz
  • Upload date:
  • Size: 84.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ulanzi_studio_niri-1.0.0.tar.gz
Algorithm Hash digest
SHA256 3df8143b0a451ef8abdfb7813e6270f8c03e38ade1f8534c7fb22d98b0f7e4ce
MD5 363b3bb3123932b511d2e4eb697addec
BLAKE2b-256 4691fda7a3e2dfab68de6c0efda3dd312ba22ec81d39a4d6e7e7276ea52944fa

See more details on using hashes here.

Provenance

The following attestation bundles were made for ulanzi_studio_niri-1.0.0.tar.gz:

Publisher: publish.yml on doitian/ulanzi-studio-niri

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ulanzi_studio_niri-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for ulanzi_studio_niri-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 598819ff7c893964f0f873adedb5186072348a4fdd044e298d7d9202d2addfdf
MD5 c0c5d42d80d19f43882f59c1862130cb
BLAKE2b-256 b5e7644b1bfd4db94157a5359766d586acac37b0496dc7b274359a79f0561a8e

See more details on using hashes here.

Provenance

The following attestation bundles were made for ulanzi_studio_niri-1.0.0-py3-none-any.whl:

Publisher: publish.yml on doitian/ulanzi-studio-niri

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page