Files
SalastilandClaude Opus 5 f965642a55 A camera that can be turned on in a call already running
The missing half of #189. A call placed as a video call already opened a
camera; a call placed as a voice call could never grow one, and the
button was hidden unless the call was on a media server - so on the two
shapes of Matrix call that do not use one, there was no camera at all.

Added and removed rather than enabled and disabled. A disabled track
keeps sending - a black rectangle at whatever frame rate the encoder
feels like - so the far end sees a dark square where a face was and
cannot tell that from a camera that has frozen. Removing the track ends
it properly, and every other client then draws the person's name. The
loopback harness below measures exactly this difference: with the old
enabled=false the far end still counts one live video track after the
camera is switched off, and with the track removed it counts none.

One gesture for all three shapes of call - a media server, a mesh
between several people, a single connection between two - because the
button is one button and the person pressing it is asking one thing.
Which shape this is belongs to the call, not to the control. On a mesh
the camera is still opened once and lent to every leg, since five
connections asking the machine for the same camera get one capture and
four refusals.

Renegotiations are now serialised. Turning a camera on and sharing a
screen a second later are two changes to one connection, and starting
the second offer while the first is unanswered leaves a peer connection
neither end can recover from. A remote track that is taken away is
dropped from the stream it arrived on, so a tile stops drawing the last
frame it received - Chromium reports that as a mute before it reports it
as an end, and on a removed track the mute is often all there is.

cameraOn is asked of the call rather than assumed, in both branches:
that block runs on every phase change, and a fixed answer put the button
back to "off" the moment a call connected.

The call UI is unchanged in shape and deliberately not Matrix-shaped -
Discord's camera (#180) and screen share (#14) get the same row of
buttons when they arrive.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-13 18:35:29 -04:00
..