Skip to content

fix(camera): read WhiteBalance, not ColorEnable, on Windows - #662

Open
yuzi-co wants to merge 1 commit into
AprilNEA:masterfrom
yuzi-co:fix/camera-white-balance-property-id
Open

fix(camera): read WhiteBalance, not ColorEnable, on Windows#662
yuzi-co wants to merge 1 commit into
AprilNEA:masterfrom
yuzi-co:fix/camera-white-balance-property-id

Conversation

@yuzi-co

@yuzi-co yuzi-co commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

VPA_WHITE_BALANCE was 6. In VideoProcAmpProperty (strmif.h), 6 is ColorEnableWhiteBalance is 7.

The constants above it are correct and contiguous through Sharpness (4), so the value reads like the next id counted on from Sharpness, skipping the two properties this backend does not map: Gamma (5) and ColorEnable (6).

Effect

Depends on the camera, and neither outcome is good:

  • Device does not support ColorEnable → the range read fails, and read_camera_state drops any control whose range errors. White balance and its auto toggle silently vanish for a camera that supports both. This is what a C930e does.
  • Device does support ColorEnable → the read succeeds and the control labelled white_balance reads and writes an unrelated boolean property.

Scope

Windows only. I checked the other two backends and both are already correct:

backend white balance id correct?
uvc.rs (macOS, raw UVC) (Processing, 0x0A)PU_WHITE_BALANCE_TEMPERATURE_CONTROL yes
uvc_linux.rs (V4L2) 0x0098_091aV4L2_CID_WHITE_BALANCE_TEMPERATURE yes
uvc_windows.rs (DirectShow) 6ColorEnable no

That is likely why it went unnoticed: the id is per-backend by nature (UVC selectors, V4L2 CIDs, and the DirectShow enum are three unrelated namespaces), and Windows is the newest backend.

Verification

On a Logitech C930e. Before — seven controls, two auto toggles, no white balance:

> openlogi camera get
  zoom: min=100 max=400 default=100 current=100
  focus: min=0 max=255 default=0 current=0
  exposure: min=-11 max=-2 default=-5 current=-5
  brightness / contrast / saturation / sharpness: min=0 max=255 default=128
  focus_auto: current=true default=true
  exposure_auto: current=true default=true

After:

  white_balance: min=2000 max=7500 default=4000 current=4000
  white_balance_auto: current=true default=true

Those bounds are corroborated by an independent DirectShow probe I wrote against the same device, which also pins the id — querying by raw property number:

[IAMVideoProcAmp]
  Gamma                  UNSUPPORTED (hr=0x80070490)
  ColorEnable            UNSUPPORTED (hr=0x80070490)     <- property 6
  WhiteBalance           min=2000 max=7500 step=1 default=4000 caps=0x3 (auto=yes)   <- property 7

A 2000..7500 range with auto capability is a Kelvin temperature; ColorEnable is a 0/1 boolean and could never report it.

Gate

Run on Windows 11 x86_64 (rustc 1.97.1):

cargo fmt --all -- --check                              exit=0
cargo clippy --workspace --all-targets -- -D warnings   exit=0
cargo test --workspace                                  exit=0
RUSTDOCFLAGS="-D warnings" cargo doc …                  exit=101

That last one fails on unmodified master too, for an unrelated reason: openlogi-hid's module doc links a cfg(not(windows)) type, so rustdoc cannot build that crate on Windows at all. #661 fixes it. With #661 applied on top of this branch, all four exit 0 — I verified that locally before dropping the cherry-pick so this PR stays independent.

Related

While probing, the same device reported four controls that CameraControl has no variant for at all — Pan, Tilt, Gain, and BacklightCompensation. Filed separately as an enhancement; not touched here.

@greptile-apps

greptile-apps Bot commented Aug 18, 2026

Copy link
Copy Markdown

Greptile Summary

This PR corrects the Windows DirectShow white-balance property identifier, changing it from ColorEnable (6) to WhiteBalance (7).

  • Updates VPA_WHITE_BALANCE to the proper DirectShow enum value.
  • Documents the skipped Gamma and ColorEnable identifiers to prevent regression.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
crates/openlogi-camera/src/uvc_windows.rs Correctly updates the Windows white-balance property ID from 6 to 7 and explains the non-mapped intervening properties.

Reviews (2): Last reviewed commit: "fix(camera): read WhiteBalance, not Colo..." | Re-trigger Greptile

@davidbudnick davidbudnick added type: bug Something is broken or behaves incorrectly platform: all Cross-platform issue labels Aug 20, 2026
@davidbudnick

Copy link
Copy Markdown
Collaborator

@yuzi-co Thanks for fixing some of the issues, can you ensure the pipeline is passing on the PR?

VPA_WHITE_BALANCE was 6. In `VideoProcAmpProperty` (strmif.h) 6 is
ColorEnable; WhiteBalance is 7. The constants above it are correct and
contiguous through Sharpness (4), so the value looks like the next id counted
on from Sharpness, skipping the two properties this backend does not map —
Gamma (5) and ColorEnable (6).

The effect depends on the camera, and neither outcome is good:

- If the device does not support ColorEnable, the range read fails and
  `read_camera_state` silently drops the control. White balance and its auto
  toggle vanish from the CLI and the GUI panel for a camera that supports both.
  This is what a C930e does.
- If the device does support ColorEnable, the read succeeds and the control
  labelled "white balance" reads and writes an unrelated boolean property.

Only the Windows backend is affected. The macOS UVC path already uses
PU_WHITE_BALANCE_TEMPERATURE_CONTROL (0x0A) and the Linux V4L2 path already
uses V4L2_CID_WHITE_BALANCE_TEMPERATURE (0x0098091a); both are correct.

Verified on a Logitech C930e. Before, `openlogi camera get` listed seven
controls and two auto toggles. After:

    white_balance: min=2000 max=7500 default=4000 current=4000
    white_balance_auto: current=true default=true

Those bounds match an independent DirectShow probe of the same device, which
also confirms the id: property 6 returns unsupported, property 7 returns
2000..7500 with auto capability — a Kelvin range, which ColorEnable (a 0/1
boolean) could never report.
@yuzi-co
yuzi-co force-pushed the fix/camera-white-balance-property-id branch from 21c5c03 to 329b1f9 Compare August 21, 2026 07:49
@yuzi-co

yuzi-co commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto master (55a6ff2) — CI is green.

The two clippy failures were not from this change. Both were clippy::chunks_exact_to_as_chunks, a lint Rust 1.98 added, firing in three files this PR does not touch:

  • crates/openlogi-hook/src/linux/wlr_foreign_toplevel.rs:229
  • crates/openlogi-hidpp/src/feature/device_friendly_name.rs:177
  • crates/openlogi-hidpp/src/feature/gestures2.rs:34

Master had already fixed all three in 4975729. This branch was cut 87 commits back, before that landed, so CI's @stable toolchain rolled onto 1.98 underneath it. The rebase applied cleanly and the diff is unchanged at 4 insertions, 1 deletion.

The fix is still needed: master still carries const VPA_WHITE_BALANCE: i32 = 6;.

Gate, re-run on the rebased tree

Local MSRV had to move first — master's bump to 1.98 meant 1.97.1 could no longer build the workspace at all. On 1.98.0:

cargo fmt --all -- --check                              exit=0
cargo clippy --workspace --all-targets -- -D warnings   exit=0
cargo test --workspace                                  exit=0
RUSTDOCFLAGS="-D warnings" cargo doc …                  exit=101

Correction to the description above

The rustdoc caveat in my original description is now wrong on two counts, so ignore it as written. That gate still fails on Windows, but the crate changed: it is no longer openlogi-hid, it is openlogi-permissions/src/lib.rs:17, whose module doc links PermissionStatus::Unknown while the enum itself is #[cfg(any(target_os = "macos", target_os = "linux"))]. On Windows the type does not exist, so the link cannot resolve.

Same bug class as #661, different crate — so #661 does not fix it, and #661 is still open regardless. I confirmed it reproduces on unmodified master by checking out 55a6ff2 and documenting that crate alone, so it is pre-existing and unrelated to this PR. CI's rustdoc job runs on Linux, which is why it stays green there.

Happy to send that one as its own fix if it is wanted separately.

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

Labels

platform: all Cross-platform issue type: bug Something is broken or behaves incorrectly

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants