Skip to content

feat(camera): add Logitech webcam support#361

Open
davidbudnick wants to merge 4 commits into
AprilNEA:masterfrom
davidbudnick:feat/logitech-webcam
Open

feat(camera): add Logitech webcam support#361
davidbudnick wants to merge 4 commits into
AprilNEA:masterfrom
davidbudnick:feat/logitech-webcam

Conversation

@davidbudnick

@davidbudnick davidbudnick commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Context

OpenLogi only managed HID++ devices — Logitech UVC webcams were invisible. This adds first-class webcam support: enumeration, live preview, and device-level image controls written over USB to the camera's own registers, so adjustments carry into Google Meet, Zoom, and OBS rather than living only in our preview.

Note

Platform support: macOS has the full feature (AVFoundation preview + IOKit controls) and is verified end-to-end on a StreamCam. Windows matches it — DirectShow enumeration and controls (IAMVideoProcAmp / IAMCameraControl) plus a Media Foundation live preview/snapshot backend (IMFSourceReader, RGB32) — and compiles clean against x86_64-pc-windows-msvc, but has not yet been exercised on real Windows hardware. Linux builds against stubs and shows no cameras.

Demo

  • Plug in a Logitech webcam (tested end-to-end on a StreamCam) → it appears on the Devices page with its product render.
  • The Camera tab shows a 720p/30 fps live preview beside the controls: Lens (Zoom / Focus / Exposure) and Image (Brightness / Contrast / Saturation / Sharpness / White balance) sliders, Auto toggles, one-click profiles (Default / Streaming / Video call / custom), and double-click-to-reset on any row. Dragging an auto-gated slider (focus / exposure / white balance) takes the control over to manual in one device write, G HUB-style.
  • The camera streams only while its tab is visible (LED off otherwise); settings persist to config.toml and re-apply after unplug/reboot.
  • CLI: openlogi camera get, openlogi camera set brightness 140, openlogi snapshot
Screenshot 2026-07-06 at 4 46 24 PM Screenshot 2026-07-06 at 4 46 21 PM Screenshot 2026-07-06 at 4 46 14 PM Screenshot 2026-07-06 at 4 46 04 PM

Changes

  • openlogi-camera crate — AVFoundation capture plus IOKit UVC controls on macOS (Processing Unit and Camera Terminal, 4-byte exposure payloads, AE-mode bitmap, batched into a single device-seize); Media Foundation capture plus DirectShow enumeration/controls on Windows: capture.rs, capture_windows.rs, uvc.rs, uvc_windows.rs, controls.rs, capture_types.rs
  • Camera tab — zero-copy 720p preview beside a sectioned control panel with Auto chips and profiles: camera_preview.rs, camera_controls.rs, app.rs
  • Asset pipeline — cameras join the depot sync; the device_camera_image manifest key and base-model variants fetch and resolve; marker-less camera metadata parses: asset/sync.rs, asset/images.rs, openlogi-assets
  • ConfigCameraControls becomes a name-keyed map (existing TOML loads unchanged) with per-camera profiles and active selection: config.rs, state.rs
  • CLIopenlogi camera get/set for every control and auto toggle; openlogi snapshot writes a PNG: cmd/camera.rs, cmd/snapshot.rs
  • Carousel — fixed-width no-shrink cards, selection-tracked scrolling, floating arrows that stop click propagation: carousel.rs

Notes

  • The Camera permission row appears in Settings only when a webcam is present; strings are translated for all 21 locales.
  • Deferred follow-ups: pan/tilt (compound 8-byte control, needs motorized hardware), vibrance (Logitech vendor XU), filters, per-app persistence.

@davidbudnick
davidbudnick marked this pull request as draft July 6, 2026 21:55
@davidbudnick
davidbudnick force-pushed the feat/logitech-webcam branch from 48bc7d8 to f0ce600 Compare July 6, 2026 21:55
@greptile-apps

greptile-apps Bot commented Jul 6, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds first-class Logitech webcam support to OpenLogi. The main changes are:

  • New openlogi-camera crate for webcam enumeration, capture, and UVC controls.
  • Camera preview and control panel in the GUI.
  • Camera profiles and per-camera settings persistence.
  • CLI commands for camera controls and snapshots.
  • Camera asset metadata and image sync support.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
crates/openlogi-camera/src/uvc.rs Adds the macOS UVC control backend with closed handling for ambiguous camera matching.
crates/openlogi-gui/src/components/camera_controls.rs Adds the camera controls panel with live resync on failed batched writes.

Reviews (13): Last reviewed commit: "fix(camera): encode CMFormatDescription ..." | Re-trigger Greptile

Comment thread crates/openlogi-camera/src/uvc.rs
Comment thread crates/openlogi-gui/src/components/camera_controls.rs
Comment thread crates/openlogi-gui/src/components/camera_controls.rs Outdated
Comment thread crates/openlogi-camera/src/uvc.rs
@davidbudnick
davidbudnick force-pushed the feat/logitech-webcam branch 6 times, most recently from 0bb4827 to fdc8528 Compare July 7, 2026 18:45
@davidbudnick
davidbudnick marked this pull request as ready for review July 7, 2026 20:08
Comment thread crates/openlogi-camera/src/uvc.rs
Comment thread crates/openlogi-gui/src/components/camera_controls.rs Outdated

@AprilNEA AprilNEA left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic feature — thanks for the thorough write-up and the end-to-end macOS testing on the StreamCam. A few things need to happen before it can land, and they're much easier from your side since you have the hardware:

1. Rebase onto master. It's ~60 commits behind and now conflicts (settings-page overhaul, Windows follow-ups, wheel/hotplug work, and the 20 locale files). Fresh conflict resolution from someone who knows the camera code will be far more reliable.

2. Move the macOS FFI to objc2. The whole workspace migrated off raw objc 0.2 to objc2 since you opened this — openlogi-hook, openlogi-inject, openlogi-agent, and openlogi-gui are all on it now — so openlogi-camera should match (the "same objc 0.2 as the GUI" note is now stale). That means Retained<T> for ownership, MainThreadMarker where the AVFoundation calls need the main thread, etc. The pattern in crates/openlogi-gui/src/platform/ and crates/openlogi-agent/src/tray.rs is the reference — it keeps the unsafe_code = "deny" + typed-ownership convention consistent across the workspace.

3. Windows is still untested on hardware — worth a pass on a real Logitech cam before shipping it first-class (or we land macOS-first and flag Windows experimental).

Happy to review again once it's rebased and on objc2. Really nice work.

@davidbudnick
davidbudnick force-pushed the feat/logitech-webcam branch 2 times, most recently from bcad272 to 9aa7d54 Compare July 21, 2026 21:07
Comment thread crates/openlogi-camera/src/uvc.rs Outdated
Comment thread crates/openlogi-gui/src/components/camera_controls.rs Outdated
@davidbudnick
davidbudnick force-pushed the feat/logitech-webcam branch 2 times, most recently from fe20e7a to 8cd9185 Compare July 21, 2026 21:22
Rebased onto current master (config.rs split into config/{settings,device}.rs,
the app.rs → app/{detail,home,widgets}.rs split, the asset-sync overhaul that
replaced collect_models with AppState::asset_models, and the 20 new locale
strings). Camera models are folded into the sync set from main.rs since
asset_models is built from the HID++ device list; the permission page stays
macOS/Linux-gated.

CLI: `openlogi snapshot` / `openlogi camera`. GUI: a Camera detail tab with a
live preview and UVC image controls, camera records in the device gallery, and
persisted per-device controls + profiles in config.
The workspace moved off raw `objc` 0.2 to `objc2` (GUI menu bar / permissions,
the hook's NSWorkspace read); openlogi-camera was the last holdout. Port both
AVFoundation modules to match:

- `Retained<T>` replaces `StrongPtr` for the session / output / delegate, so
  ownership is leak-proof by construction (no hand-balanced retain/release).
- The frame delegate is registered with `ClassBuilder` (the objc2 analog of
  `ClassDecl`); it stays a stateless background-queue `NSObject` subclass, so no
  `MainThreadMarker` is needed — AVFoundation's session start/stop and the
  sample-buffer callback are all off-main.
- `block2::RcBlock` replaces `block::ConcreteBlock` for the requestAccess
  completion handler.
- Enumeration uses `objc2::rc::autoreleasepool` instead of a manual
  `NSAutoreleasePool` new/drain pair.

Deps: objc 0.2 + block 0.1 → objc2 (workspace) + block2; drops the
`unexpected_cfgs` allow the old objc macros needed. `unsafe_code = "deny"` with
local `#[expect(unsafe_code)]` is unchanged.
@davidbudnick
davidbudnick force-pushed the feat/logitech-webcam branch from 8cd9185 to c43f25a Compare July 21, 2026 21:29
Comment thread crates/openlogi-camera/src/uvc.rs
Comment thread crates/openlogi-gui/src/components/camera_controls.rs
Comment thread crates/openlogi-gui/src/components/camera_controls.rs
Comment thread crates/openlogi-gui/src/components/camera_controls.rs
Comment thread crates/openlogi-gui/src/components/camera_controls.rs
Comment thread crates/openlogi-gui/src/components/camera_controls.rs Outdated
@davidbudnick
davidbudnick force-pushed the feat/logitech-webcam branch from 2d4a48e to 26ea8d2 Compare July 21, 2026 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants