Skip to content

Comments

fix(linux/kms): resolve connector names in output_name config#4762

Open
itsDNNS wants to merge 4 commits intoLizardByte:masterfrom
itsDNNS:fix/output-name-connector-support
Open

fix(linux/kms): resolve connector names in output_name config#4762
itsDNNS wants to merge 4 commits intoLizardByte:masterfrom
itsDNNS:fix/output-name-connector-support

Conversation

@itsDNNS
Copy link

@itsDNNS itsDNNS commented Feb 23, 2026

Description

This PR adds support for DRM connector names in output_name and introduces pre_probe_cmd for virtual display lifecycle management on Linux/KMS.

Commit 1 - fix(linux/kms): resolve connector names in output_name config
When output_name is set to a DRM connector name like DP-2, util::from_view() silently converts it to a garbage integer. Added resolve_display_name() that accepts both numeric indices (backward compatible) and connector names.

Commit 2 - feat: add pre_probe_cmd config option
New config option (same JSON syntax as global_prep_cmd) that runs commands before encoder probing. Enables virtual display on-demand lifecycle: enable on stream connect, disable on disconnect. Client parameters exposed as env vars (SUNSHINE_CLIENT_WIDTH, HEIGHT, FPS, HDR).

Commit 3 - fix(linux/kms): refresh card_descriptors when connector not found
When pre_probe_cmd enables a virtual display, the connector is not yet in card_descriptors (populated at startup). resolve_display_name() now retries once after refreshing the display list.

Commit 4 - fix(video): add connector name fallback in refresh_displays
When output_name is a connector name, it won't match the numeric display_names list, causing the wrong monitor to be streamed. Added fallback that appends the connector name directly.

Use case: Virtual monitor driven by custom EDID firmware, kept disabled when not streaming. On stream connect, pre_probe_cmd enables the display via kscreen-doctor, on disconnect the undo command disables it.

Example sunshine.conf:

output_name = DP-2
pre_probe_cmd = [{"do":"sunshine-display-manager on","undo":"sunshine-display-manager off"}]

Screenshot

N/A (no UI changes)

Issues Fixed or Closed

Roadmap Issues

Type of Change

  • feat: New feature (non-breaking change which adds functionality)
  • fix: Bug fix (non-breaking change which fixes an issue)
  • docs: Documentation only changes
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semicolons, etc.)
  • refactor: Code change that neither fixes a bug nor adds a feature
  • perf: Code change that improves performance
  • test: Adding missing tests or correcting existing tests
  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Other changes that don't modify src or test files
  • revert: Reverts a previous commit
  • BREAKING CHANGE: Introduces a breaking change (can be combined with any type above)

Checklist

  • Code follows the style guidelines of this project
  • Code has been self-reviewed
  • Code has been commented, particularly in hard-to-understand areas
  • Code docstring/documentation-blocks for new or existing methods/components have been added or updated
  • Unit tests have been added or updated for any new or modified functionality

AI Usage

  • None: No AI tools were used in creating this PR
  • Light: AI provided minor assistance (formatting, simple suggestions)
  • Moderate: AI helped with code generation or debugging specific parts
  • Heavy: AI generated most or all of the code changes

AI tool used: Claude Code (Opus 4.6). The concept, architecture, and testing were done by the author; Claude Code assisted with implementation, debugging, and commit messages.

Dennis Braun added 4 commits February 23, 2026 10:25
When a user sets output_name to a DRM connector name like "DP-2" or
"HDMI-A-1", util::from_view() silently converts the non-numeric string
to a garbage integer (e.g. "DP-2" becomes 23172), causing display init
to fail with "Couldn't find monitor [23172]".

This is a UX trap because Sunshine's own KMS logs show connector names
(e.g. "Monitor 1 is DP-2: ..."), leading users to copy those names into
their config.

Add resolve_display_name() that accepts both numeric indices (backward
compatible) and DRM connector names. Connector names are parsed using
the existing kms::from_view() and matched against card_descriptors
already populated by kms_display_names().
New config option `pre_probe_cmd` (same JSON syntax as `global_prep_cmd`)
that runs before encoder probing. This allows enabling a virtual display
on demand rather than keeping it active permanently.

The "do" commands run before display configuration and encoder probing
in launch() and resume(), with client parameters exposed as environment
variables (SUNSHINE_CLIENT_WIDTH, HEIGHT, FPS, HDR). The "undo" commands
run on probe failure, cancel, and session disconnect.
When pre_probe_cmd enables a virtual display (e.g. via kscreen-doctor),
the connector is not yet present in card_descriptors which were populated
at startup. resolve_display_name() now retries once after refreshing
the display list via kms_display_names(), allowing dynamically enabled
connectors to be resolved.
When output_name is a DRM connector name like "DP-2", it won't match
the numeric display_names list (["0", "1", ...]). Without this fix,
the code falls through to index 0, streaming the wrong monitor.

Add a fallback that appends the connector name to display_names when
no numeric match is found, allowing display_t::init() to resolve it
via resolve_display_name().
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
1 New issue
1 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@ReenigneArcher
Copy link
Member

Thank you for the PR. I'm assuming since you didn't use our PR template this is AI generated?

Can you please use our PR template? https://github.com/LizardByte/.github/blob/master/.github/pull_request_template.md?plain=1

@ReenigneArcher ReenigneArcher added the ai PR has signs of heavy ai usage (either indicated by user or assumed) label Feb 23, 2026
@itsDNNS
Copy link
Author

itsDNNS commented Feb 23, 2026

Thanks for the feedback! Updated the PR description with the official template.

To answer your question: yes, the implementation was done with AI assistance (Claude Code / Opus 4.6). I designed the approach and did all testing on my setup (virtual monitor via custom EDID on KMS/Wayland), Claude helped with the actual code changes. Marked as "Heavy" in the AI Usage section for full transparency.

@Dregu
Copy link
Contributor

Dregu commented Feb 23, 2026

I'll say we've needed this feature forever, but the pr's have just been disappearing for years. I was just thinking of doing it yesterday too. Needs to work with wlgrab and actual virtual displays though, i.e. HEADLESS-3 from wl_display_names, that's an even bigger mess than physical connector order.

I'm currently porting the wlr-screencopy code to prefer the new ext-image-copy-capture proto that will replace it, since Hyprland merged icc yesterday. I could also add this feature to wlgrab on the side...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai PR has signs of heavy ai usage (either indicated by user or assumed)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants