Skip to content

Comms: Zoom talkback station in Pro (ZComms port, SDK 7.1.5, Private comms) - #1207

Merged
iamfatness merged 4 commits into
mainfrom
codex/comms-talkback
Nov 11, 2026
Merged

iamfatness merged 4 commits into
mainfrom
codex/comms-talkback

Conversation

@iamfatness

Copy link
Copy Markdown
Owner

What

Adds a Comms tab to Pro: ZComms-style talkback to talent in the meeting, built in Pro's own look. The operator presses a key to speak privately to one person, a group, or everyone (ALL CALL), and talent hears it through Zoom.

Talkback runs inside Pro's own Zoom engine. It has to: Zoom allows one participant per process, and a second app joining on the same account collides with it.

Changes

  • Engine: ZComms' talkback layer is ported into the shared corevideo-zoom-engine (engine-comms, engine/comms/**, fake comms). CoreVideo Edge uses the same files byte-for-byte; Edge PR Redesign CoreVideo Pro UI with tabbed top-bar layout #5 is merged.
    • It follows the ZComms delivery rules: the meeting mic must be open; one paced membership-call queue; unity volume at create and ducking while keyed; ALREADY_EXIST counts as present; mono sends.
    • Held keys are leased, so a lost release can't leave a key on.
  • Zoom SDK 7.1.5, needed for IMeetingTalkbackController.
  • Core relay: the shell sends comms-* commands. The core sends zoom-comms-state every second, and null on leave.
  • Comms page:
    • Talk keys, ALL CALL, and editing who is on each channel.
    • Mic, sidetone and tone settings, a meter, and an ops strip.
    • Keys 1-9 and Space work from the keyboard. Keys are released when the window loses focus or the operator leaves the tab.
    • Cells are rebuilt only when the channel layout changes, so a press always gets its release.
  • Private comms switch, off by default and remembered between restarts:
    • On: Pro's meeting mic becomes a silent virtual mic. Pro unmutes only after Zoom confirms that mic started. If Zoom doesn't confirm within 5 seconds, Pro stays muted and the page says why talkback is silent.
    • Off: the operator's mic is left alone. Turning it off leaves them muted; Pro never unmutes their real mic.

Tests

  • 55 native comms tests.
  • MediaCore 3184 and WinUI 2035 tests pass.
  • The talkback probe passes 53/53, with Private comms on and off.
  • The page probe (--verify-comms-page) passes.
  • The full native suite was not re-run after the Private comms change. Before it, one D3D timing test unrelated to Comms failed in the full run and passed when run alone.

Not proven

Nothing here has been run in a real Zoom meeting yet. Before relying on it, one session with Pro's account as host or co-host and a guest on the Zoom desktop app should confirm:

  • the guest actually hears talkback;
  • Zoom reports the silent mic started while Pro's meeting mic is muted;
  • the operator's account has the raw-data licence Private comms needs;
  • raw video and ISO recording still work on SDK 7.1.5.

The EngineHost path does not relay Comms state yet.

🤖 Generated with Claude Code

Ports the ZComms talkback station into Pro's Zoom engine, byte-identical to
CoreVideo Edge's native/zoom-engine comms files @ Edge 28c06bc (engine-comms,
engine/comms/** incl. mic_guard, fake-comms, miniaudio). Pro-specific hooks in
main.cpp / fake-engine.cpp: start, handle_line first, on_meeting_status first
in onMeetingStatusChanged, set_capture_only from the join line (Pro joins are
never capture-only, so the operator's meeting mic is never touched), shutdown
before Leave/CleanUPSDK.

Media core: ZoomCommsRelay (Edge's CommsRelay verbatim) validates the shell's
comms-* requests (key/latch with leaseMs, assign, mic, sidetone-out,
sidetone, tone, gain, release-all); JsonRpcServer answers them lock-free (no
coreMutex, no assembly slot); key-ups are urgent in the mailbox. The engine's
comms_state is re-keyed to camelCase in ZoomEngineRuntime and pushed as a
latest-wins "zoom-comms-state" fact on the zoom pump (repeated 1/s while
held; comms:null on Leave, engine loss and restart).

Build: Meeting SDK 7.1.5.43953 (scripts + docs); comms libraries in
native/CMakeLists.txt (NOMINMAX scoped to the comms TUs).

Tests: 45 native comms tests (relay, core, protocol, mic guard, ported ZComms,
runtime). scripts/probe-comms.mjs drives the real core against the fake engine
end to end (40 checks). Real Zoom talkback is untested.

Docs: docs/reference/comms-talkback.md, CLAUDE.md row + SDK line, engine README.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A Comms tab (after Audio) driven by the core's zoom-comms-state facts:
a cell is a talk key (TalkKey: press = down, release/capture loss = up,
Click never used, hover/pressed visuals suppressed so colour is engine
truth), ALL CALL, Latch, Edit talent with one chip per channel, Settings
(mic, sidetone output, sidetone/tone, gain, station counters), lamps
LINK/MTG MIC/CHANNEL/TX, one-line ops strip that expands to history.
Explicit not-in-meeting / waiting / not-up (verbatim reason) states.

CommsViewModel carries Edge's behaviour and JSON; cells, people, device
pickers and ops history are synced in place (ObservableCollectionSync, no
Reset) and only on a structure change, so a press never loses its release.
Held keys are leased (1500 ms, renewed every 500 ms); every key goes up on
focus leaving the page, window deactivate, tab change, meeting end or a
dropped report; shutdown sends comms-release-all. Digits 1-9 and Space are
panel-scoped. Colours are Pro tokens only: on air = StudioAirBrush (Pro's
on-air red) with StudioBackgroundBrush text, armed = StudioWarningBrush.

MediaCore: ZoomCommsProtocol (verbs, state parser, reply), IZoomCommsTransport
on MediaCoreBridgeService, supervisor push of zoom-comms-state, key-ups on
the EngineHost reserved lane.

Probe: CoreVideoPro.WinUI.exe --verify-comms-page (offscreen, no core),
added to scripts/test-studio-layout.ps1. Tests: CommsViewModelTests (29),
ZoomCommsProtocolTests (8).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Owner ruling 2026-11-10. A "Private comms" strip button, OFF by default and
persisted (ProductionOutputPreferences.CommsPrivate):
- ON: the meeting mic becomes the never-fed silent virtual mic exactly like
  the capture-only path (MicGuard: operator muted at once, HasRawdataLicense,
  unmute only after onMicInitialize, 5 s timeout stays muted with the
  "Talkback is silent" reason, drop = release then mute).
- OFF (and ON -> OFF): setExternalAudioSource(nullptr), operator left MUTED,
  never auto-unmuted; the ops log says so. A non-capture-only meeting ending
  also removes the silent mic.

Engine (shared with Edge): comms_private {"on"} verb; MicGuard install
condition is capture_only || private_on, new Act::Mute / Act::Uninstall,
private on again retries after a give-up, capture-only ignores private;
CommsCore keeps the request across meetings and reports comms_state.private
(capture_only || requested); fake engine runs the real MicGuard over a
scripted SDK (COREVIDEO_FAKE_SILENT_MIC=never, COREVIDEO_FAKE_OPERATOR_MUTED=1,
fakecomms::SetCaptureOnly from the join line; default capture-only).

Core: comms-private relayed (OFF never refused, urgent lane). Shell: toggle,
persistence, re-assert when a report disagrees (at most every 2 s).

Tests: MicGuard +7, CommsCore +1, CommsProtocol +1, CommsRelay +1,
CommsViewModel +4, ZoomCommsProtocol updated; probe-comms 53/53 incl. the
private on/off/never-unmute sequence; page probe checks the toggle.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@iamfatness
iamfatness merged commit 1284c8b into main Nov 11, 2026
17 checks passed
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