#81 landed voice and video over m.call.*, which is Matrix's original one-to-one
signalling: one offer, one answer, one other person. A room with three people in it
has no call in moho - there is no m.call.notify, no MSC3401 group session, and
nothing in the daemon that mentions either.
The window is ready for it. The video surface already draws a fitted grid of any
number of tiles, lights whoever is talking, and lets one person be enlarged
(components/CallStage.tsx, VideoStage.tsx) - that work was done against a call of
five and only ever fed by two. What is missing is the signalling underneath.
What is needed
MSC3401 group call membership (m.call.member state) and m.call.notify for the
ring, or Element Call's current shape if that has settled by the time this is
picked up - it should be read again before anything is written, since this part of
Matrix moves.
A peer connection per participant in the renderer, which is what Call
(lib/webrtc.ts) would need generalising to hold.
Leave and rejoin without ending it for everybody else, which is the difference
between a group call and a conference somebody hosts.
Done looks like: three people in a room can be in the same call, and the grid that
already exists draws them.
#81 landed voice and video over `m.call.*`, which is Matrix's original one-to-one
signalling: one offer, one answer, one other person. A room with three people in it
has no call in moho - there is no `m.call.notify`, no MSC3401 group session, and
nothing in the daemon that mentions either.
The window is ready for it. The video surface already draws a fitted grid of any
number of tiles, lights whoever is talking, and lets one person be enlarged
(`components/CallStage.tsx`, `VideoStage.tsx`) - that work was done against a call of
five and only ever fed by two. What is missing is the signalling underneath.
**What is needed**
- MSC3401 group call membership (`m.call.member` state) and `m.call.notify` for the
ring, or Element Call's current shape if that has settled by the time this is
picked up - it should be read again before anything is written, since this part of
Matrix moves.
- A peer connection per participant in the renderer, which is what `Call`
(`lib/webrtc.ts`) would need generalising to hold.
- Leave and rejoin without ending it for everybody else, which is the difference
between a group call and a conference somebody hosts.
**Done looks like:** three people in a room can be in the same call, and the grid that
already exists draws them.
Reference: Element. Follows #81.
A call in a room, between everybody in it: m.call.member state says who is in one, and the media is a mesh of one connection per pair.
Joining is starting. Publishing this end's membership is what makes a call exist; the difference is only whether anybody was there first. Memberships carry an expiry and are refreshed while still here, so a client that dies mid-call stops being a participant.
Who calls whom is a property of the pair, not of who arrived first — the smaller key calls the larger, computed identically on both sides. Otherwise both ends call and the call collides with itself.
One capture for the whole call, lent to each leg: five connections asking for the same camera get one capture and four refusals.
A bar at the top of a room where a call is happening, because a group call has no invitation. The header buttons start a room call in a channel and ring somebody in a DM.
The permission trap, which would otherwise fail silently: a membership is a state event, and a room's default lets only moderators send those — so a call in an ordinary room is one nobody else can join. Starting a call now lowers m.call.member to power 0 where this account may say so, and the refusal explains itself where it may not. This was found by hitting it: the second account's join came back M_FORBIDDEN: Event is not authorized.
Verified end to end between two real accounts on two different homeservers — @salastil:poa.st and @salastil:matrix.salastil.com, in a room created for the test:
A joins → m.call.member published; B's own view of the room reports it
B's window → "@salastil:poa.st is in a call — Join / Join with video"
B joins → both ends: "Connected", 2 tiles each, live audio track on both
B hangs up → B's stage gone, bar back to offering Join; A back to 1 tile
Audio only, because this machine has no camera — the fallback path did its job.
Two things worth knowing. This is moho-to-moho: Element Call now runs through an SFU (LiveKit) rather than a mesh, so it will not join one of these — full interop needs the focus half of MSC3401 and is a separate piece of work. And a mesh costs one upload stream per other participant, which is fine for the handful of people a room call usually is and would not be fine for thirty.
Finished — https://git.salastil.com/Salastil/nobilis/commit/6fd10f7 and https://git.salastil.com/Salastil/moho/commit/ce64d76
A call in a room, between everybody in it: `m.call.member` state says who is in one, and the media is a mesh of one connection per pair.
- **Joining is starting.** Publishing this end's membership is what makes a call exist; the difference is only whether anybody was there first. Memberships carry an expiry and are refreshed while still here, so a client that dies mid-call stops being a participant.
- **Who calls whom** is a property of the pair, not of who arrived first — the smaller key calls the larger, computed identically on both sides. Otherwise both ends call and the call collides with itself.
- **One capture for the whole call**, lent to each leg: five connections asking for the same camera get one capture and four refusals.
- **A bar at the top of a room** where a call is happening, because a group call has no invitation. The header buttons start a room call in a channel and ring somebody in a DM.
- **The permission trap**, which would otherwise fail silently: a membership is a *state* event, and a room's default lets only moderators send those — so a call in an ordinary room is one nobody else can join. Starting a call now lowers `m.call.member` to power 0 where this account may say so, and the refusal explains itself where it may not. This was found by hitting it: the second account's join came back `M_FORBIDDEN: Event is not authorized`.
**Verified end to end between two real accounts on two different homeservers** — `@salastil:poa.st` and `@salastil:matrix.salastil.com`, in a room created for the test:
```
A joins → m.call.member published; B's own view of the room reports it
B's window → "@salastil:poa.st is in a call — Join / Join with video"
B joins → both ends: "Connected", 2 tiles each, live audio track on both
B hangs up → B's stage gone, bar back to offering Join; A back to 1 tile
```
Audio only, because this machine has no camera — the fallback path did its job.
**Two things worth knowing.** This is moho-to-moho: Element Call now runs through an SFU (LiveKit) rather than a mesh, so it will not join one of these — full interop needs the focus half of MSC3401 and is a separate piece of work. And a mesh costs one upload stream per other participant, which is fine for the handful of people a room call usually is and would not be fine for thirty.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
#81 landed voice and video over
m.call.*, which is Matrix's original one-to-onesignalling: one offer, one answer, one other person. A room with three people in it
has no call in moho - there is no
m.call.notify, no MSC3401 group session, andnothing in the daemon that mentions either.
The window is ready for it. The video surface already draws a fitted grid of any
number of tiles, lights whoever is talking, and lets one person be enlarged
(
components/CallStage.tsx,VideoStage.tsx) - that work was done against a call offive and only ever fed by two. What is missing is the signalling underneath.
What is needed
m.call.memberstate) andm.call.notifyfor thering, or Element Call's current shape if that has settled by the time this is
picked up - it should be read again before anything is written, since this part of
Matrix moves.
Call(
lib/webrtc.ts) would need generalising to hold.between a group call and a conference somebody hosts.
Done looks like: three people in a room can be in the same call, and the grid that
already exists draws them.
Reference: Element. Follows #81.
Finished — https://git.salastil.com/Salastil/nobilis/commit/6fd10f7 and https://git.salastil.com/Salastil/moho/commit/ce64d76
A call in a room, between everybody in it:
m.call.memberstate says who is in one, and the media is a mesh of one connection per pair.m.call.memberto power 0 where this account may say so, and the refusal explains itself where it may not. This was found by hitting it: the second account's join came backM_FORBIDDEN: Event is not authorized.Verified end to end between two real accounts on two different homeservers —
@salastil:poa.stand@salastil:matrix.salastil.com, in a room created for the test:Audio only, because this machine has no camera — the fallback path did its job.
Two things worth knowing. This is moho-to-moho: Element Call now runs through an SFU (LiveKit) rather than a mesh, so it will not join one of these — full interop needs the focus half of MSC3401 and is a separate piece of work. And a mesh costs one upload stream per other participant, which is fine for the handful of people a room call usually is and would not be fine for thirty.